Skip to content

Commit

Permalink
Merge pull request #1823 from iorveth/transaction_failure_case_event
Browse files Browse the repository at this point in the history
Introduce TransactionFailed event and adjust related core logic & test coverage
  • Loading branch information
bedeho committed Nov 28, 2020
2 parents 11d4f09 + 5d61f1e commit 4865e9b
Show file tree
Hide file tree
Showing 24 changed files with 179 additions and 72 deletions.
147 changes: 102 additions & 45 deletions runtime-modules/content-directory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,11 @@ use codec::{Codec, Decode, Encode};
use frame_support::storage::IterableStorageMap;

use frame_support::{
decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure, traits::Get, Parameter,
decl_event, decl_module, decl_storage,
dispatch::{DispatchError, DispatchResult},
ensure,
traits::Get,
Parameter,
};
#[cfg(feature = "std")]
pub use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -1625,64 +1629,115 @@ decl_module! {
Ok(())
}

/// Batch transaction
#[weight = 10_000_000] // TODO: adjust weight
pub fn transaction(origin, actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>, operations: Vec<OperationType<T>>) -> DispatchResult {
/// Batch transaction
#[weight = 10_000_000] // TODO: adjust weight
pub fn transaction(origin, actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>, operations: Vec<OperationType<T>>) -> DispatchResult {

// Ensure maximum number of operations during atomic batching limit not reached
Self::ensure_number_of_operations_during_atomic_batching_limit_not_reached(&operations)?;
// Ensure maximum number of operations during atomic batching limit not reached
Self::ensure_number_of_operations_during_atomic_batching_limit_not_reached(&operations)?;

//
// == MUTATION SAFE ==
//
//
// == MUTATION SAFE ==
//

// This BTreeMap holds the T::EntityId of the entity created as a result of executing a `CreateEntity` `Operation`
let mut entity_created_in_operation = BTreeMap::new();
// This BTreeMap holds the T::EntityId of the entity created as a result of executing a `CreateEntity` `Operation`
let mut entity_created_in_operation = BTreeMap::new();

// Create raw origin
let raw_origin = origin.into().map_err(|_| Error::<T>::OriginCanNotBeMadeIntoRawOrigin)?;
// Create raw origin
let raw_origin = origin.into().map_err(|_| Error::<T>::OriginCanNotBeMadeIntoRawOrigin)?;

for (index, operation_type) in operations.into_iter().enumerate() {
let origin = T::Origin::from(raw_origin.clone());
match operation_type {
OperationType::CreateEntity(create_entity_operation) => {
Self::create_entity(origin, create_entity_operation.class_id, actor)?;
for (index, operation_type) in operations.into_iter().enumerate() {
let origin = T::Origin::from(raw_origin.clone());
match operation_type {
OperationType::CreateEntity(create_entity_operation) => {
Self::ensure_transaction_failed_event(
Self::create_entity(origin, create_entity_operation.class_id, actor),
actor,
index
)?;

// entity id of newly created entity
let entity_id = Self::next_entity_id() - T::EntityId::one();
entity_created_in_operation.insert(index, entity_id);
},
OperationType::AddSchemaSupportToEntity(add_schema_support_to_entity_operation) => {
let entity_id = operations::parametrized_entity_to_entity_id(
&entity_created_in_operation, add_schema_support_to_entity_operation.entity_id
},
OperationType::AddSchemaSupportToEntity(add_schema_support_to_entity_operation) => {
let entity_id =
Self::ensure_transaction_failed_event(
operations::parametrized_entity_to_entity_id(
&entity_created_in_operation, add_schema_support_to_entity_operation.entity_id
),
actor,
index
)?;

let schema_id = add_schema_support_to_entity_operation.schema_id;

let property_values =
Self::ensure_transaction_failed_event(
operations::parametrized_property_values_to_property_values(
&entity_created_in_operation, add_schema_support_to_entity_operation.parametrized_property_values
),
actor,
index
)?;
Self::ensure_transaction_failed_event(
Self::add_schema_support_to_entity(origin, actor, entity_id, schema_id, property_values),
actor,
index
)?;
let schema_id = add_schema_support_to_entity_operation.schema_id;
let property_values = operations::parametrized_property_values_to_property_values(
&entity_created_in_operation, add_schema_support_to_entity_operation.parametrized_property_values
)?;
Self::add_schema_support_to_entity(origin, actor, entity_id, schema_id, property_values)?;
},
OperationType::UpdatePropertyValues(update_property_values_operation) => {
let entity_id = operations::parametrized_entity_to_entity_id(
&entity_created_in_operation, update_property_values_operation.entity_id
)?;
let property_values = operations::parametrized_property_values_to_property_values(
&entity_created_in_operation, update_property_values_operation.new_parametrized_property_values
)?;
Self::update_entity_property_values(origin, actor, entity_id, property_values)?;
},
}
}

// Trigger event
Self::deposit_event(RawEvent::TransactionCompleted(actor));

Ok(())
}
},
OperationType::UpdatePropertyValues(update_property_values_operation) => {
let entity_id =
Self::ensure_transaction_failed_event(
operations::parametrized_entity_to_entity_id(
&entity_created_in_operation, update_property_values_operation.entity_id
),
actor,
index
)?;

let property_values =
Self::ensure_transaction_failed_event(
operations::parametrized_property_values_to_property_values(
&entity_created_in_operation, update_property_values_operation.new_parametrized_property_values
),
actor,
index
)?;

Self::ensure_transaction_failed_event(
Self::update_entity_property_values(origin, actor, entity_id, property_values),
actor,
index
)?;
},
}
}

// Trigger event
Self::deposit_event(RawEvent::TransactionCompleted(actor));

Ok(())
}
}
}

impl<T: Trait> Module<T> {
/// Deposits an `TransactionFailed` event if an error during `transaction` extrinsic execution occured
fn ensure_transaction_failed_event<R, E: Into<DispatchError>>(
result: Result<R, E>,
actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
index: usize,
) -> Result<R, DispatchError> {
match result {
Err(e) => {
Self::deposit_event(RawEvent::TransactionFailed(actor, index as u32));
Err(e.into())
}
Ok(result) => Ok(result),
}
}

/// Updates corresponding `Entity` `reference_counter` by `reference_counter_delta`.
fn update_entity_rc(
entity_id: T::EntityId,
Expand Down Expand Up @@ -2827,6 +2882,7 @@ decl_event!(
Nonce = <T as Trait>::Nonce,
SideEffects = Option<ReferenceCounterSideEffects<T>>,
SideEffect = Option<(<T as Trait>::EntityId, EntityReferenceCounterSideEffect)>,
FailedAt = u32,
{
CuratorGroupAdded(CuratorGroupId),
CuratorGroupRemoved(CuratorGroupId),
Expand All @@ -2851,5 +2907,6 @@ decl_event!(
InsertedAtVectorIndex(Actor, EntityId, PropertyId, VecMaxLength, Nonce, SideEffect),
EntityOwnershipTransfered(EntityId, EntityController, SideEffects),
TransactionCompleted(Actor),
TransactionFailed(Actor, FailedAt),
}
);
3 changes: 2 additions & 1 deletion runtime-modules/content-directory/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,13 +433,14 @@ type RawTestEvent = RawEvent<
Nonce,
Option<ReferenceCounterSideEffects<Runtime>>,
Option<(EntityId, EntityReferenceCounterSideEffect)>,
u32,
>;

pub fn get_test_event(raw_event: RawTestEvent) -> TestEvent {
TestEvent::test_events(raw_event)
}

pub fn assert_event_success(tested_event: TestEvent, number_of_events_after_call: usize) {
pub fn assert_event(tested_event: TestEvent, number_of_events_after_call: usize) {
// Ensure runtime events length is equal to expected number of events after call
assert_eq!(System::events().len(), number_of_events_after_call);

Expand Down
2 changes: 1 addition & 1 deletion runtime-modules/content-directory/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ pub fn add_entity_schemas_support() -> (
));

// Last event checked
assert_event_success(
assert_event(
entity_schema_support_added_event,
number_of_events_before_calls + 2,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ fn add_class_schema_success() {
get_test_event(RawEvent::ClassSchemaAdded(FIRST_CLASS_ID, SECOND_SCHEMA_ID));

// Last event checked
assert_event_success(class_schema_added_event, number_of_events_before_call + 2);
assert_event(class_schema_added_event, number_of_events_before_call + 2);
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn add_curator_group_success() {
get_test_event(RawEvent::CuratorGroupAdded(FIRST_CURATOR_GROUP_ID));

// Event checked
assert_event_success(
assert_event(
curator_group_created_event,
number_of_events_before_call + 1,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn add_curator_to_group_success() {
));

// Event checked
assert_event_success(
assert_event(
curator_group_curator_added_event,
number_of_events_before_call + 1,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn add_maintainer_to_class_success() {
));

// Event checked
assert_event_success(maintainer_added_event, number_of_events_before_call + 1);
assert_event(maintainer_added_event, number_of_events_before_call + 1);
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn clear_entity_property_vector_success() {
));

// Last event checked
assert_event_success(
assert_event(
entity_property_vector_cleared_event,
number_of_events_before_calls + 1,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn create_class_success() {
let class_created_event = get_test_event(RawEvent::ClassCreated(FIRST_CLASS_ID));

// Event checked
assert_event_success(class_created_event, number_of_events_before_call + 1);
assert_event(class_created_event, number_of_events_before_call + 1);
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ fn create_entity_success() {
get_test_event(RawEvent::EntityCreated(actor, next_entity_id() - 1));

// Last event checked
assert_event_success(entity_created_event, number_of_events_before_call + 1);
assert_event(entity_created_event, number_of_events_before_call + 1);
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fn insert_at_entity_property_vector_success() {
));

// Last event checked
assert_event_success(
assert_event(
inserted_at_vector_index_event,
number_of_events_before_calls + 1,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fn remove_at_entity_property_vector_success() {
));

// Last event checked
assert_event_success(
assert_event(
removed_at_vector_index_event,
number_of_events_before_calls + 1,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ fn remove_curator_from_group_success() {
));

// Event checked
assert_event_success(
assert_event(
curator_group_curator_removed_event,
number_of_events_before_call + 1,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ fn remove_curator_group_success() {
get_test_event(RawEvent::CuratorGroupRemoved(FIRST_CURATOR_GROUP_ID));

// Event checked
assert_event_success(
assert_event(
curator_group_removed_event,
number_of_events_before_call + 1,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn remove_entity_success() {
get_test_event(RawEvent::EntityRemoved(actor, next_entity_id() - 1));

// Last event checked
assert_event_success(entity_removed_event, number_of_events_before_call + 1);
assert_event(entity_removed_event, number_of_events_before_call + 1);
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fn remove_maintainer_from_class_success() {
));

// Event checked
assert_event_success(maintainer_removed_event, number_of_events_before_call + 1);
assert_event(maintainer_removed_event, number_of_events_before_call + 1);
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn set_curator_group_status_success() {
));

// Event checked
assert_event_success(
assert_event(
curator_group_status_set_event,
number_of_events_before_call + 1,
);
Expand Down

0 comments on commit 4865e9b

Please sign in to comment.