Skip to content

Releases: RailsEventStore/rails_event_store

v0.19.0

06 Nov 11:10
b8f5122

Choose a tag to compare

RailsEventStore

  • Add: publish_events(events) API which allows publishing a collection of events. Handlers are executed in the order the events were provided. First all handlers to the 1st event, then all handlers to the 2nd event and so on...

    publish_events([e0, e1]) is equivalent to publish_event([e0]); publish_event([e1]) but the events are stored transactionally (when using RailsEventStoreActiveRecord).

RubyEventStore

  • Add: publish_events(events) API which allows publishing a collection of events.
  • Fix: Fix one-shot (dynamic) subscribers behavior when exception occurs during processing a block. A dynamic subscriber was not unsubscribed when an exception happened. Not it will be unsubscribed.
  • Fix: RubyEventStore::Event#hash method was implemented. Now identical events (in terms of class, event_id and data) can be safely used as keys in Hash or members of a Set. Notice: metadata is ignored when comparing events.
  • Change: RubyEventStore::InMemoryRepository uses append_to_stream(events, stream_name, expected_version) API instead of create(event, stream_name)
  • Change: RubyEventStore::InMemoryRepository can detect concurrent writes to the same stream

RailsEventStoreActiveRecord

  • Breaking: Uses two tables instead of one to save events and events in streams separately. Use following commands to migrate schema and data:

    rails generate rails_event_store_active_record:v1_v2_migration
    rake db:migrate
    

    This migration is intended to be run in offline mode. You need to edit this migration file and fill out the def preserve_positions?(stream_name) method based on the instructions you will find there.

    If by any chance you cannot migrate the schema right now you can (for some limited) time switch to old repository, available as RailsEventStoreActiveRecord::LegacyEventRepository:

    Rails.application.configure do
      config.to_prepare do
        Rails.configuration.event_store = RailsEventStore::Client.new(
          repository: RailsEventStoreActiveRecord::LegacyEventRepository.new
        )
      end
    end

    Mind that we're going to eventually remove RailsEventStoreActiveRecord::LegacyEventRepository in one of next major releases.

  • Breaking: Passing UUID is no longer accepted as expected_version of previous event in a stream. Use integers as sequence numbers for that purpose.

  • Breaking: delete_stream no longer removes an events. The new behaviour is as follows:

    • EventRepository#delete_stream will unlink events from given stream, leave it in others
    • LegacyEventRepository#delete_stream will move events from given stream to global stream named all
  • Change: 3 ways of providing expected_version. Read more at our expected_version option explained article in the documentation

  • Change: Properly detects race conditions in case of concurrent writes to the same stream using optimistic locking strategy when a proper expected_version is used. Read more at our expected_version option explained article in the documentation

  • Change: append_to_stream(events, stream_name, expected_version) API instead of create(event, stream_name) which allows storing a collection of events transactionally and optimistic locking

  • Add: LegacyEventRepository to support old database schema and allow to prepare for migration to new schema used by EventRepository.

  • Breaking: RailsEventStoreActiveRecord::EventRepository cannot be initialized with an adapter.

  • Add: RailsEventStoreActiveRecord::EventRepository can append the same event to multiple streams without the need to duplicate the event with a different UUID.

AggregateRoot

  • Change: Properly provides lower layer with expected_version to detect concurrent writes to the same stream. Can raise RubyEventStore::EventDuplicatedInStream (aliased as RailsEventStore::EventDuplicatedInStream) when there is a concurrency conflict.
  • Change: unpublished_events is publicly available, read-only iterator.

RailsEventStore::RSpec

  • no changes

BoundedContext

  • no changes

v0.18.2

18 Oct 11:13

Choose a tag to compare

RailsEventStore

  • no changes

RubyEventStore

  • no changes

RailsEventStoreActiveRecord

  • Fix: Improve Async dispatcher compatibility with Rails 5.1 - #132

AggregateRoot

  • no changes

RailsEventStore::RSpec

  • no changes

BoundedContext

  • no changes

v0.18.1

11 Oct 17:59

Choose a tag to compare

RailsEventStore

  • no changes

RubyEventStore

  • no changes

RailsEventStoreActiveRecord

  • no changes

AggregateRoot

  • no changes

RailsEventStore::RSpec

  • Fix: Bump rails_event_store dependency to point to the latest release. Before 18a7b96 it was impossible to resolve rails_event_store and rails_event_store-rspec of the same version number.

BoundedContext

  • no changes

v0.18.0

25 Sep 20:02

Choose a tag to compare

RailsEventStore

  • Add: Support for asychronous event handlers with ActiveJobDispatcher [#103]

ActiveJobDispatcher is a new dispatcher ready to use with RES as a replacement of DefaultDispatcher.
The main improvement is that if a handler class is an ancestor of ActiveJob::Base it will be handled asynchronously.

Comes in two flavours: Inline, which is a default proxy_strategy and AfterCommit.

config.event_store = RailsEventStore::Client.new(
  event_broker: RailsEventStore::EventBroker.new(
    dispatcher: RailsEventStore::ActiveJobDispatcher.new(
      proxy_strategy: RailsEventStore::AsyncProxyStrategy::AfterCommit.new
    )
  )
)

Use RailsEventStore::AsyncProxyStrategy::AfterCommit when your queue is handled by Resque, Sidekiq or in general by different datastore than RailsEventStoreActiveRecord itself.

Use RailsEventStore::AsyncProxyStrategy::Inline when your queue is DelayedJob or any queue using underlying database - same as the one for RailsEventStoreActiveRecord .

As a consequence subscriber can be now just a class:

module Denormalizers
  class OrderSubmitted < ApplicationJob
    queue_as :default

    def perform(*args)
      call(YAML.load(args.first))
    end

    private
    def call(event)
      # implementation
    end
  end
end

Rails.application.config.event_store.tap do |es|
  es.subscribe(Denormalizers::OrderSubmitted, [Events::OrderSubmitted])
end

RubyEventStore

  • no changes

RailsEventStoreActiveRecord

  • no changes

AggregateRoot

  • Change: unpublished_events collection is now public but read-only

RailsEventStore::RSpec

  • Fix: missing release task in Makefile
  • Fix: uninitialized constant RSpec::Matchers when running rake [#115]
  • Fix: undefined method 'failure_message' for HaveApplied [#118]
  • Change: auto-configure RSpec [#120]
  • Change: bump RES in dev dependencies from ~> 0.15.0 to ~> 0.17.0
  • Change: implemented basic failure_message for HavePublished

BoundedContext

  • First release of a gem supporting technical part of separating logical application parts.

Add to Gemfile as following:

gem 'bounded_context`

Now you can launch generator if you're on Rails:

rails g bounded_context:generator inventory 

That would create inventory/lib/inventory.rb

module Inventory
end

It will also make sure code is autoloaded there as long as you stick to require_dependency over regular require. See following blogpost to learn more about this.

module Rails513
  class Application < Rails::Application
    config.paths.add 'inventory/lib', eager_load: true
  end
end

v0.17.0

15 Sep 21:39
dc4a4c1

Choose a tag to compare

This release adds RailsEventStore::RSpec to the repository.

RailsEventStore

  • no changes

RubyEventStore

  • no changes

RailsEventStoreActiveRecord

  • no changes

AggregateRoot

  • no changes

RailsEventStore::RSpec

  • no changes

v0.16.0

14 Sep 14:16

Choose a tag to compare

AggregateRoot

  • Change: AggregateRoot#apply can handle multiple events
  • Fix: #109 - AggregateRoot#apply returns applied events instead of all unpublished_events.

This is an important change as usually apply is the last method called inside your public methods and the resul is returned outside.

Developers can opt-out from this behavior by using

def apply(*events)
  super
  nil
end

in a class.

or by explicitly returning nil or self from public methods.

  def supply(quantity)
    raise NotRegistered unless @store_id
    apply(ProductSupplied.new(data: {
      store_id: @store_id,
      sku: @sku,
      quantity: quantity,
    }))
    nil
  end

Other gems

  • no changes

v0.15.0

30 Aug 13:29

Choose a tag to compare

In this release we've slightly changed release versioning policy - all gems from now on will get the same version number. This also means that all gems will be released even if there were changes in only one of them.

RailsEventStore

  • no changes

RubyEventStore

  • no changes

RailsEventStoreActiveRecord

  • no changes

AggregateRoot

  • no changes