Documentation
¶
Overview ¶
Package atom implements the Transaction/Unit of Work pattern with compensating actions for ensuring atomicity in non-database operations like network requests, file I/O, and other side effects.
Overview ¶
Atom provides a way to group multiple operations into a single unit of work that can be rolled back if any operation fails. Each operation is paired with a compensating function that undoes its effects.
Basic Usage ¶
tx := atom.NewTransaction()
defer func() {
if !tx.IsCommitted() {
_ = tx.Rollback(ctx)
}
}()
err := tx.Do(ctx, "create-file",
func(ctx context.Context) error {
return os.WriteFile("/tmp/file.txt", []byte("data"), 0644)
},
func(ctx context.Context) error {
return os.Remove("/tmp/file.txt")
},
)
if err != nil {
return err
}
return tx.Commit(ctx)
Operations with Options ¶
Use functional options for advanced configuration including timeouts and retry:
err := tx.Do(ctx, "api-call", operationFunc, compensateFunc, atom.WithTimeout(5*time.Second), atom.WithCompensationRetry(atom.DefaultRetryOptions()))
Savepoints ¶
Create savepoints for partial rollback:
sp := tx.CreateSavepoint("checkpoint")
// ... more operations ...
tx.RollbackToSavepoint(ctx, sp) // rolls back only operations after savepoint
Hooks ¶
Register callbacks at various points in the transaction lifecycle:
tx.AddHook(atom.BeforeCommit, func(ctx context.Context, tx *atom.Transaction) error {
// validation logic
return nil
})
Hook types: BeforeCommit, AfterCommit, BeforeRollback, AfterRollback, BeforeOperation, AfterOperation.
Observability ¶
Implement the Observer interface for metrics and tracing:
tx := atom.NewTransaction(atom.WithObserver(&MyObserver{}))
Logging ¶
Optionally configure a *slog.Logger for structured logging:
tx := atom.NewTransaction(atom.WithLogger(slog.Default()))
By default, no logging is performed. When a logger is set, warnings and info messages are logged for rollback failures, hook failures, and retry attempts.
Error Types ¶
The errors subpackage provides typed errors:
- OperationError: wraps errors from operation execution
- RollbackError: wraps errors from compensation (supports multi-error unwrap)
- HookError: wraps errors from hook execution
- PanicError: wraps recovered panics
Thread Safety ¶
All Transaction methods are safe for concurrent use. The implementation uses RWMutex and atomic operations internally.
Index ¶
- type CompensatingFunc
- type Hook
- type HookFunc
- type HookType
- type LoggingObserver
- func (l *LoggingObserver) OnCommit(ctx context.Context)
- func (l *LoggingObserver) OnOperationEnd(ctx context.Context, name string, duration time.Duration, err error)
- func (l *LoggingObserver) OnOperationStart(ctx context.Context, name string)
- func (l *LoggingObserver) OnRollback(ctx context.Context, errors []error)
- type MetricsObserver
- func (m *MetricsObserver) OnCommit(ctx context.Context)
- func (m *MetricsObserver) OnOperationEnd(ctx context.Context, name string, duration time.Duration, err error)
- func (m *MetricsObserver) OnOperationStart(ctx context.Context, name string)
- func (m *MetricsObserver) OnRollback(ctx context.Context, errors []error)
- type NoOpObserver
- type Observer
- type OperationFunc
- type OperationHook
- type OperationHookFunc
- type OperationOption
- type OperationRecord
- type RetryOptions
- type Savepoint
- type Transaction
- func (tx *Transaction) AddCriticalHook(hookType HookType, fn HookFunc)
- func (tx *Transaction) AddCriticalOperationHook(hookType HookType, fn OperationHookFunc)
- func (tx *Transaction) AddDefaultHook(hookType HookType, fn HookFunc)
- func (tx *Transaction) AddHook(hookType HookType, fn HookFunc)
- func (tx *Transaction) AddOperationHook(hookType HookType, fn OperationHookFunc)
- func (tx *Transaction) ClearAllHooks()
- func (tx *Transaction) ClearHooks(hookType HookType)
- func (tx *Transaction) Commit(ctx context.Context) error
- func (tx *Transaction) CreateSavepoint(name string) *Savepoint
- func (tx *Transaction) Do(ctx context.Context, name string, operation OperationFunc, ...) error
- func (tx *Transaction) GetHistory() []OperationRecord
- func (tx *Transaction) GetLogger() *slog.Logger
- func (tx *Transaction) GetObserver() Observer
- func (tx *Transaction) IsCommitted() bool
- func (tx *Transaction) IsPending() bool
- func (tx *Transaction) IsRolledBack() bool
- func (tx *Transaction) OperationCount() int
- func (tx *Transaction) Rollback(ctx context.Context) error
- func (tx *Transaction) RollbackToSavepoint(ctx context.Context, sp *Savepoint) error
- type TransactionOption
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CompensatingFunc ¶
CompensatingFunc is a function that undoes/compensates for an operation
type HookFunc ¶
type HookFunc func(context.Context, *Transaction) error
HookFunc is a function that gets called at specific points in the transaction lifecycle
type HookType ¶
type HookType int
HookType represents the type of hook to execute
const ( // BeforeCommit is called before committing the transaction // Critical by default - failures block commit BeforeCommit HookType = iota // AfterCommit is called after successful commit // Non-critical by default - already committed, can't undo AfterCommit // BeforeRollback is called before rolling back operations // Non-critical by default - we're already in failure mode BeforeRollback // AfterRollback is called after rollback completes // Non-critical by default - rollback already done AfterRollback // BeforeOperation is called before each operation executes // Critical by default - failures block the operation BeforeOperation // AfterOperation is called after each operation completes (success or failure) // Non-critical by default - operation already executed AfterOperation )
type LoggingObserver ¶
type LoggingObserver struct{}
LoggingObserver is an Observer implementation that logs events using alog
func NewLoggingObserver ¶
func NewLoggingObserver() *LoggingObserver
NewLoggingObserver creates a new LoggingObserver
func (*LoggingObserver) OnCommit ¶
func (l *LoggingObserver) OnCommit(ctx context.Context)
func (*LoggingObserver) OnOperationEnd ¶
func (*LoggingObserver) OnOperationStart ¶
func (l *LoggingObserver) OnOperationStart(ctx context.Context, name string)
func (*LoggingObserver) OnRollback ¶
func (l *LoggingObserver) OnRollback(ctx context.Context, errors []error)
type MetricsObserver ¶
type MetricsObserver struct {
OperationCount int64
SuccessCount int64
FailureCount int64
TotalDuration time.Duration
CommitCount int64
RollbackCount int64
RollbackErrorCount int64
}
MetricsObserver is a sample Observer that collects basic metrics This is a reference implementation; production use would integrate with actual metrics systems like Prometheus, OpenTelemetry, etc.
func NewMetricsObserver ¶
func NewMetricsObserver() *MetricsObserver
NewMetricsObserver creates a new MetricsObserver
func (*MetricsObserver) OnCommit ¶
func (m *MetricsObserver) OnCommit(ctx context.Context)
func (*MetricsObserver) OnOperationEnd ¶
func (*MetricsObserver) OnOperationStart ¶
func (m *MetricsObserver) OnOperationStart(ctx context.Context, name string)
func (*MetricsObserver) OnRollback ¶
func (m *MetricsObserver) OnRollback(ctx context.Context, errors []error)
type NoOpObserver ¶
type NoOpObserver struct{}
NoOpObserver is an Observer implementation that does nothing Useful as a default or for testing
func (NoOpObserver) OnCommit ¶
func (NoOpObserver) OnCommit(ctx context.Context)
func (NoOpObserver) OnOperationEnd ¶
func (NoOpObserver) OnOperationStart ¶
func (NoOpObserver) OnOperationStart(ctx context.Context, name string)
func (NoOpObserver) OnRollback ¶
func (NoOpObserver) OnRollback(ctx context.Context, errors []error)
type Observer ¶
type Observer interface {
// OnOperationStart is called before an operation begins execution
OnOperationStart(ctx context.Context, name string)
// OnOperationEnd is called after an operation completes (success or failure)
OnOperationEnd(ctx context.Context, name string, duration time.Duration, err error)
// OnCommit is called after a successful commit
OnCommit(ctx context.Context)
// OnRollback is called after a rollback completes
// errors contains any errors that occurred during compensation
OnRollback(ctx context.Context, errors []error)
}
Observer is an interface for observing transaction lifecycle events Implementations can be used for metrics, tracing, logging, or other observability needs
type OperationFunc ¶
OperationFunc is the main operation to execute
type OperationHook ¶
type OperationHook struct {
Fn OperationHookFunc
Critical bool
}
OperationHook represents a registered operation hook with its criticality setting
type OperationHookFunc ¶
OperationHookFunc is a function that gets called before/after each operation It receives the operation name and index in addition to the standard hook parameters
type OperationOption ¶ added in v0.0.2
type OperationOption func(*operationOptions)
OperationOption is a functional option for the Do method.
func WithCompensationRetry ¶ added in v0.0.2
func WithCompensationRetry(r *RetryOptions) OperationOption
WithCompensationRetry configures retry behavior for the compensating function.
func WithTimeout ¶ added in v0.0.2
func WithTimeout(d time.Duration) OperationOption
WithTimeout sets a timeout for the operation (0 means no timeout).
type OperationRecord ¶
OperationRecord is the public view of operation metadata
type RetryOptions ¶
type RetryOptions struct {
// MaxRetries is the maximum number of retry attempts (0 means no retries)
MaxRetries int
// InitialDelay is the delay before the first retry
InitialDelay time.Duration
// BackoffMultiplier is the multiplier for exponential backoff (e.g., 2.0 doubles delay each retry)
BackoffMultiplier float64
// MaxDelay is the maximum delay between retries
MaxDelay time.Duration
}
RetryOptions configures retry behavior for compensating functions
func DefaultRetryOptions ¶
func DefaultRetryOptions() *RetryOptions
DefaultRetryOptions returns sensible default retry options
type Savepoint ¶
type Savepoint struct {
// contains filtered or unexported fields
}
Savepoint represents a point in the transaction that can be rolled back to
type Transaction ¶
type Transaction struct {
// contains filtered or unexported fields
}
Transaction manages a sequence of operations with rollback capability
func NewTransaction ¶
func NewTransaction(opts ...TransactionOption) *Transaction
NewTransaction creates a new transaction with the given options.
func (*Transaction) AddCriticalHook ¶
func (tx *Transaction) AddCriticalHook(hookType HookType, fn HookFunc)
AddCriticalHook adds a critical hook that will block the operation if it fails
func (*Transaction) AddCriticalOperationHook ¶
func (tx *Transaction) AddCriticalOperationHook(hookType HookType, fn OperationHookFunc)
AddCriticalOperationHook adds a critical operation hook that blocks the operation if it fails
func (*Transaction) AddDefaultHook ¶
func (tx *Transaction) AddDefaultHook(hookType HookType, fn HookFunc)
AddDefaultHook adds a hook with default criticality based on hook type
func (*Transaction) AddHook ¶
func (tx *Transaction) AddHook(hookType HookType, fn HookFunc)
AddHook adds a non-critical hook to the transaction
func (*Transaction) AddOperationHook ¶
func (tx *Transaction) AddOperationHook(hookType HookType, fn OperationHookFunc)
AddOperationHook adds a non-critical operation hook Operation hooks are called before/after each Do() call
func (*Transaction) ClearAllHooks ¶
func (tx *Transaction) ClearAllHooks()
ClearAllHooks removes all registered hooks
func (*Transaction) ClearHooks ¶
func (tx *Transaction) ClearHooks(hookType HookType)
ClearHooks removes all hooks of a specific type
func (*Transaction) Commit ¶
func (tx *Transaction) Commit(ctx context.Context) error
Commit finalizes the transaction, making rollback no longer possible It executes BeforeCommit and AfterCommit hooks
func (*Transaction) CreateSavepoint ¶
func (tx *Transaction) CreateSavepoint(name string) *Savepoint
CreateSavepoint creates a savepoint at the current position in the transaction This allows partial rollback to this point using RollbackToSavepoint
func (*Transaction) Do ¶
func (tx *Transaction) Do(ctx context.Context, name string, operation OperationFunc, compensate CompensatingFunc, opts ...OperationOption) error
Do executes an operation and registers its compensating function. If the operation fails, it automatically triggers a rollback. The name parameter is optional (can be empty string). Options like timeout and compensation retry can be passed as functional options.
func (*Transaction) GetHistory ¶
func (tx *Transaction) GetHistory() []OperationRecord
GetHistory returns a copy of the operation history for debugging
func (*Transaction) GetLogger ¶
func (tx *Transaction) GetLogger() *slog.Logger
GetLogger returns the current logger, if any
func (*Transaction) GetObserver ¶
func (tx *Transaction) GetObserver() Observer
GetObserver returns the current observer, if any
func (*Transaction) IsCommitted ¶
func (tx *Transaction) IsCommitted() bool
IsCommitted returns whether the transaction has been committed
func (*Transaction) IsPending ¶
func (tx *Transaction) IsPending() bool
IsPending returns true if the transaction is neither committed nor rolled back
func (*Transaction) IsRolledBack ¶
func (tx *Transaction) IsRolledBack() bool
IsRolledBack returns whether the transaction has been rolled back
func (*Transaction) OperationCount ¶
func (tx *Transaction) OperationCount() int
OperationCount returns the number of recorded operations
func (*Transaction) Rollback ¶
func (tx *Transaction) Rollback(ctx context.Context) error
Rollback executes all compensating functions in reverse order (LIFO) It executes BeforeRollback and AfterRollback hooks
func (*Transaction) RollbackToSavepoint ¶
func (tx *Transaction) RollbackToSavepoint(ctx context.Context, sp *Savepoint) error
RollbackToSavepoint rolls back operations to the specified savepoint Operations after the savepoint are compensated in reverse order (LIFO) The transaction remains pending and can continue with new operations
type TransactionOption ¶ added in v0.0.2
type TransactionOption func(*transactionOptions)
TransactionOption is a functional option for NewTransaction.
func WithLogger ¶ added in v0.0.2
func WithLogger(logger *slog.Logger) TransactionOption
WithLogger sets the logger for the transaction. If set, the transaction will log warnings and info messages using this logger.
func WithObserver ¶ added in v0.0.2
func WithObserver(obs Observer) TransactionOption
WithObserver sets the observer for the transaction. Only one observer can be set; setting a new one replaces the previous.