eventastic 0.1.0

Eventastic is an opinionated fork of Eventually-rs. It enforces the use of transactions and handles idempotency.
Documentation
eventastic-0.1.0 has been yanked.

Eventastic

This is an opinionated fork of Eventually-rs.

Eventastic enforces the use of transactions, handles idempotency and removes command handling abstractions.

Examples

See full examples in examples/bank

// Setup postgres repo

 let connection_options =
     PgConnectOptions::from_str("postgres://postgres:password@localhost/postgres")?;

 let pool_options = PoolOptions::default();

 let repository = PostgresRepository::new(connection_options, pool_options).await?;

 // Start transaction
 let mut transaction = repository.transaction().await?;

 let account_id = Uuid::new_v4();
 let event_id = Uuid::new_v4();
 let add_event_id = Uuid::new_v4();

 // Open bank account

 let event = AccountEvent::Open(event_id, account_id, 21);

 let mut account = Account::record_new(event)?;

 // Add funds to newly created event
 let add_event = AccountEvent::Add(add_event_id, 324);

 // Record takes in the transaction, as it does idempotency checks with the db.
 account
     .record_that(&mut transaction, add_event.clone())
     .await?;

 // Save uncommitted events in the db.
 transaction.store(&mut account).await?;

 // Since we have access to the transaction
 // We could use a transactional outbox to store our side effects

 // Commit the transaction
 transaction.commit().await?;

 // Get the aggregate from the db
 let mut transaction = repository.transaction().await?;

 let mut account: Context<Account> = transaction.get(&account_id).await?;

 assert_eq!(account.state().balance, 345);

 // Trying to apply the same event id but with different content gives us an IdempotencyError
 let changed_add_event = AccountEvent::Add(add_event_id, 123);

 let err = account
     .record_that(&mut transaction, changed_add_event)
     .await
     .expect_err("failed to get error");

 assert!(matches!(err, RecordError::IdempotencyError(_, _)));

 // Applying the already applied event, will be ignored and return Ok
 account.record_that(&mut transaction, add_event).await?;

 // Balance hasn't changed since the event wasn't actually applied
 assert_eq!(account.state().balance, 345);

 println!("Got account {account:?}");
 Ok(())