Changelog

v1.2.0 - 2026-01-27

Breaking Changes

⚠️ Projection Handle Signature Change - The Projection.Handle method now includes a transaction parameter to enable atomic read model and checkpoint updates.

Before (v1.1.0):

func (p *MyProjection) Handle(ctx context.Context, event es.PersistedEvent) error

After (v1.2.0):

func (p *MyProjection) Handle(ctx context.Context, tx *sql.Tx, event es.PersistedEvent) error

Migration Guide:

All projections must update their Handle method signatures. The transaction parameter behavior:

When Using the Same Database as Event Store: Use the tx parameter to execute database operations atomically with checkpoint updates:

func (p *UserReadModel) Handle(ctx context.Context, tx *sql.Tx, event es.PersistedEvent) error {
    // Use tx for database operations
    _, err := tx.ExecContext(ctx, 
        "INSERT INTO users (id, name) VALUES ($1, $2) "+
        "ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name",
        userID, name)
    return err
}

When Writing to External Destinations: Ignore the tx parameter for projections writing to external systems (message brokers, separate databases, search engines):

func (p *MessageBrokerPublisher) Handle(ctx context.Context, tx *sql.Tx, event es.PersistedEvent) error {
    // Ignore tx - use message broker client
    _ = tx
    msg := message.NewMessage(event.EventID.String(), event.Payload)
    return p.publisher.Publish(event.EventType, msg)
}

Benefits: - Atomic Updates: Read model changes and checkpoints are committed together - Data Consistency: Eliminates the "projection succeeded but checkpoint failed" scenario - Simplified Code: No need to manage separate transactions in SQL projections

Improvements

  • Transaction-based projection processing for better consistency
  • All adapters (PostgreSQL, MySQL, SQLite) pass transaction to projections
  • Processor manages transaction lifecycle automatically

v1.1.0 - 2026-01-19

New Features

  • RunModeOneOff for Projection Testing - Added RunModeOneOff to enable synchronous projection processing for integration tests. Projections now support two modes:
  • RunModeContinuous (default) - Production mode that runs forever
  • RunModeOneOff - Testing mode that processes available events and exits cleanly

This makes integration testing significantly easier and more deterministic. See the One-Off Projection Processing guide for details.

Improvements

  • All projection processors (postgres, mysql, sqlite) support the new run mode
  • Comprehensive integration test examples added
  • No breaking changes - fully backward compatible

Previous Releases

See the GitHub Releases page for information about earlier versions.