Idea on handling transactions?
Is there anyone who has tried ddd with transactions?
Hi @SeaRoll, my 2 cents: The application layer should begin the transaction (as early as possible) as it coordinates the workflow of domain operations.
Example (untested):
func (s *Service) PerformOperation(ctx context.Context, input InputDTO) error {
tx := s.db.Begin() // Start the transaction
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// Perform domain operations using repositories
err := s.repo.DoSomething(tx, input)
if err != nil {
tx.Rollback()
return err
}
err = s.repo.DoAnotherThing(tx, input)
if err != nil {
tx.Rollback()
return err
}
return tx.Commit().Error // Commit the transaction
}
Amazing, thank you!
does not this approach lead to leakage on the application/domain? 🤔
Kind of does.
I would suggest to call
op, err := s.repository.BeginOperation(context.Context) (operation.Operation, error)
defer op.Commit() // op.Rollback()
In this case you can provide operation op as is, or even inject it to context ctx = op.Context() to be extracted on repository level later.
In both ways you work with abstract operation that makes your actions atomic, however it doesn't lead to leakage of the repository internals.