Releases: RailsEventStore/rails_event_store
v0.40.1
RailsEventStore
- no changes
RubyEventStore
- no changes
RailsEventStoreActiveRecord
- no changes
AggregateRoot
- Fix:
AggregateRootmodule is not opinionated on aggregate initializer and its arguments [7c64c02]
RailsEventStore::RSpec
- no changes
BoundedContext
- no changes
RubyEventStore::Browser
- no changes
RubyEventStore::ROM
- no changes
v0.40.0
RailsEventStore
- no changes
RubyEventStore
-
Change:
RubyEventStore::Event#correlate_withreturnsselfto allow chaining [#601] -
Change: Deprecate
RubyEventStore::Mappers::MissingEncryptionKeyconst. It has been moved toRubyEventStore::Mappers::Transformation::Encryption::MissingEncryptionKeywhere it is used. Old const continues to work until next release [#619] -
Add: Introduce the concept of mapper pipeline. That allows composing mapper transformations. RES mappers now consist of such transformations [#572, #600]
Usage:
module RubyEventStore module Mappers class Default < PipelineMapper def initialize(serializer: YAML, events_class_remapping: {}) super(Pipeline.new( transformations: [ Transformation::EventClassRemapper.new(events_class_remapping), Transformation::SymbolizeMetadataKeys.new, Transformation::Serialization.new(serializer: serializer), ] )) end end end end
module RubyEventStore module Mappers class EncryptionMapper < PipelineMapper def initialize(key_repository, serializer: YAML, forgotten_data: ForgottenData.new) super(Pipeline.new( transformations: [ Transformation::Encryption.new(key_repository, serializer: serializer, forgotten_data: forgotten_data), Transformation::Serialization.new(serializer: serializer), ] )) end end end end
-
Change: All errors are now descendant of
RubyEventStore::Error[#620] -
Change: Deprecate
RubyEventStore::PubSub::Dispatcher,RubyEventStore::PubSub::SubscriptionsandRubyEventStore::PubSub::Brokerconsts. They have been moved toRubyEventStore::Dispatcher,RubyEventStore::SubscriptionsandRubyEventStore::Brokerrespectively. Old consts continues to work until next release [#624]
RailsEventStoreActiveRecord
-
Add: Support JSON data types in ActiveRecord database migration [#598]
Usage:
rails generate rails_event_store_active_record:migration --data_type=jsonb # or json
AggregateRoot
-
Change:
AggregateRoot.onnow depends onRubyEventStore::Event#type[#578, #579] -
Add: New way to specify custom apply strategy [#584, #587, #597]
Was:
class OrderWithCustomStrategy include AggregateRoot def apply_strategy @apply_strategy ||= CustomOrderApplyStrategy.new end end
Is now:
class OrderWithCustomStrategy include AggregateRoot.with_strategy(->{ CustomOrderApplyStrategy.new }) end
-
Fix: Allow specifying
AggregateRoot.onarguments as strings, in addition to passing event class. This opens possibility to use this API with Proto events [#578, #588]Usage:
Google::Protobuf::DescriptorPool.generated_pool.build do add_message "res_testing.OrderPaid" do # ... end end module ResTesting OrderPaid = Google::Protobuf::DescriptorPool.generated_pool.lookup("res_testing.OrderPaid").msgclass end class Order include AggregateRoot on 'res_testing.OrderPaid' do |_event| @status = :paid end end order = ResTesting::Order.new order_paid = RubyEventStore::Proto.new( event_id: "f90b8848-e478-47fe-9b4a-9f2a1d53622b", data: ResTesting::OrderPaid.new ) order.apply(order_paid)
-
Remove: Deprecated
AggregateRoot#loadandAggregateRoot#storeare gone [1ea7d2f] -
Add: Instrumentation for
AggregateRoot::Repository#load,AggregateRoot::Repository#storeandAggregateRoot::Repository#with_aggregatemethods [#591]Usage:
ar_repository = InstrumentedRepository.new( AggregateRoot::Repository.new(event_store), ActiveSupport::Notifications )
RailsEventStore::RSpec
- no changes
BoundedContext
- no changes
RubyEventStore::Browser
-
Change: Browser's API now returns error 404 when event not found (previously it was error 500) [#603]
-
Add: Show link to correlation stream, if
correlation_idpresent. For now, it only supports default correlation metadata field (correlation_id) and prefix ($by_correlation_id_) [#609] -
Add: Show link to causation stream, if
causation_idpresent. For now, it only supports default correlation metadata field (causation_id) and prefix ($by_causation_id_) [#610] -
Add: Show limited (to 20 events) list of caused events by viewed event. [5c462f4]
-
Change: Display timestamps in more readable format [#613]
-
Change: Display more accurate browser
<title />(instead of hardcodedRubyEventStore::Browser) [#613] -
Add: Show link to the event which caused viewed event [#614]
-
Add: Show link to event type stream (for example:
$by_type_DummyEvent). For now only supports default prefix. [#617]
RubyEventStore::ROM
- Change: Update required versions of
dry-types,romandrom-sqldependencies. It may affect your project if you depend on those gems [#595]
v0.39.0
RailsEventStore
- Remove: Deprecated
from(:head)has been removed from read specification. Whenfrom(event_id)is not specified, we always read from head [#565]
RubyEventStore
-
Remove: Deprecated
from(:head)has been removed from read specification. Whenfrom(event_id)is not specified, we always read from head [#565] -
Change: New default cipher (
aes-256-gcm) forRubyEventStore::Mappers::EncryptionMapper. From now on we follow OpenSSL recommendation for using an Authenticated Encryption mode. This change is backwards-compatible, you can still decrypt ciphertext encrypted with previous cipher as this is stored within encryption metadata [#567, a13658c] -
Fix:
RubyEventStore::Mappers::NullMappernow follows behaviour of mappers more strictly by turning events into serialized records on serialization. It still does not perform serialization and is thus recommended for use in testing [#552, #575]If you've relied on NullMapper + InMemoryRepository returning objects of the same
object_id, this is a breaking change. You may replicate that behaviour with:class NULL def self.serialized_record_to_event(record) record end def self.event_to_serialized_record(event) event end end
Bear in mind though such workaround will not support many already existing repository features (i.e.
of_type) and may become even more trouble in the future.
RailsEventStoreActiveRecord
- Add: Migrating existing events is now supported on sqlite (version 3.24 or newer is required) [#446, #574]
AggregateRoot
- no changes
RailsEventStore::RSpec
- no changes
BoundedContext
- no changes
RubyEventStore::Browser
- no changes
RubyEventStore::ROM
- no changes
In this release we've also ended testing support for Ruby 2.3. This means that while Rails Event Store might continue to work without issues on that Ruby version, new development won't be targeting compatibility with it.
v0.38.1
RailsEventStore
- no changes
RubyEventStore
- Fix:
RubyEventStore::Mappers::EncryptionKey#decryptforces UTF-8 encoding on decrypted message [ec23b10]
RailsEventStoreActiveRecord
- no changes
AggregateRoot
- no changes
RailsEventStore::RSpec
- no changes
BoundedContext
- no changes
RubyEventStore::Browser
- no changes
RubyEventStore::ROM
- no changes
v0.38.0
RailsEventStore
- no changes
RubyEventStore
-
Add: Introducing
RubyEventStore::Mappers::EncryptionMapperto allow partial encryption of event data attributes [#451, #361]More in GDPR documentation.
RailsEventStoreActiveRecord
- no changes
AggregateRoot
- no changes
RailsEventStore::RSpec
- no changes
BoundedContext
- no changes
RubyEventStore::Browser
- no changes
RubyEventStore::ROM
- no changes
v0.37.0
RailsEventStore
-
Remove: Deprecated
RailsEventStore::Client#read_eventis no more -
Add: Convenience
Enumerable#mapandEnumerable#reduceon read API [#538]Was:
event_store.read.stream(stream_name).each.reduce {|_, ev| apply(ev) }
Becomes:
event_store.read.stream(stream_name).reduce {|_, ev| apply(ev) }
RubyEventStore
-
Remove: Deprecated
RubyEventStore::Client#read_event,RubyEventStore::SpecificationResult#count,RubyEventStore::SpecificationResult#direction,RubyEventStore::SpecificationResult#stream_nameandRubyEventStore::SpecificationResult#global_stream?are no more [#534] -
Remove: Migrator script from deprecated read API removed [#534]
-
Add: Convenience
Enumerable#mapandEnumerable#reduceon read API [#538]Was:
event_store.read.stream(stream_name).each.reduce {|_, ev| apply(ev) }
Becomes:
event_store.read.stream(stream_name).reduce {|_, ev| apply(ev) }
-
Add:
RubyEventStore::Mappers::InstrumentedMapperto allow instrumenting serialization and deserialization [#540]Usage with
ActiveSupport::Notifications:RubyEventStore::Client.new( mapper: RubyEventStore::Mappers::InstrumentedMapper.new( mapper, ActiveSupport::Notifications ) ) ActiveSupport::Notifications.subscribe("serialize.mapper.rails_event_store") do ... end ActiveSupport::Notifications.subscribe("deserialize.mapper.rails_event_store") do ... end
-
Change:
RubyEventStore::Specification#of_typeaccepts now also a single event type in addition to an array of event types [#542] -
Add: Introduce
RubyEventStore::Specification#toin order to specify stop point for the read operation [#528, #529] -
Add: Minimal linter (in form of shared RSpec tests) to verify event interface. Useful when you intend to implement your own Event class [#550, #553]
RailsEventStoreActiveRecord
- no changes
AggregateRoot
- Change: Restore
AggregateRoot::Repositoryand shift persistence responsibility back to it from aggregate. Deprecatesloadandstoremethods onAggregateRootmodule [#547]
RailsEventStore::RSpec
- no changes
BoundedContext
- no changes
RubyEventStore::Browser
- Change: Migrate to Elm 0.19, no change in functionality [#548]
RubyEventStore::ROM
- no changes
v0.36.0
RailsEventStore
-
Remove: Deprecated
RailsEventStore::ActiveJobDispatcher,RailsEventStore::ActiveJobDispatcher::ActiveJobSchedulerandRailsEventStore::AsyncProxyStrategy::AfterCommitare no more [#518] -
Fix: Ensure dispatch for after commit strategy works in case of raise in
after_commitcallback [#519, #183] -
Fix: Ensure
RailsEventStore::AsyncHandlercovers use case of background job systems integrated withoutActiveJobinterface [#507, 7d249f5]
RubyEventStore
- Remove: Deprecated
RubyEventStore:: AsyncDispatcherandRubyEventStore::AsyncProxyStrategy::Inlineare no more [#518]
RailsEventStoreActiveRecord
- no changes
AggregateRoot
- no changes
RailsEventStore::RSpec
- no changes
BoundedContext
- no changes
RubyEventStore::Browser
- no changes
RubyEventStore::ROM
-
Add: JSON support in migrations to allow specifying JSON or JSONB for
dataandmetadatacolumns [#524] -
Add: Upsert capability for updating events [#476]
RailsEventStoreActiveRecord::Legacy
No longer released from now on (deprecated in release 0.18.0).
v0.35.0
RailsEventStore
-
Add:
APP_TEMPLATEto bootstrap Rails applications withrails_event_storegem.Usage:
rails new -m https://raw.githubusercontent.com/RailsEventStore/rails_event_store/master/APP_TEMPLATE my_rails_app
RubyEventStore
-
Add: Support for
HashandArrayas allowed types inRubyEventStore::Metadata[#501] -
Add: Debugging API to get size of a stream to read [#503]
client.read.stream('GoldCustomers').of_type([Customer::GoldStatusGranted]).count # => 42
RailsEventStoreActiveRecord
-
Change: Default column type for event
dataandmetadatais now binary. This allows wider range of exchangeable components (i.e. encryption mapper). In general it is more suitable type to store anything [#490, #308]As it always is with data schema changes, a migration is required for existing data. Running migration:
rails g rails_event_store_active_record:binary_data_and_metadata rails db:migrateFeel free to inspect and change generated migration. Make sure to check if your RDBMS can run this migration online and whether that meets your operational requirements.
https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html#online-ddl-column-operationsYou can defer this migration for some time if you don't plan to use Protobuf at the moment. The future code in Rails Event Store and its extensions will however assume the columns are binary from now on and can't guarantee full compatibility.
AggregateRoot
-
Change: Make
aggregate_rootdepend onruby_event_store[4926dc4]Initially, when introducing this gem the event store API was simpler and we had plans to swap with with http_event_store. This has changed over the years and now
aggregate_rootis released along other RES gems.
RailsEventStore::RSpec
- no changes
BoundedContext
- no changes
RubyEventStore::Browser
- no changes
RubyEventStore::ROM
- no changes
RailsEventStoreActiveRecord::Legacy
- no changes
v0.34.0
RailsEventStore
-
Add: New read API to filter read events by type
event_store.read.of_type[#472]event_store = RailsEventStore::Client.new TweetPosted = Class.new(RubyEventStore::Event) TweetRetweeted = Class.new(RubyEventStore::Event) TweetLiked = Class.new(RubyEventStore::Event) event_store.publish(TweetPosted.new(event_id: '54994b0e-4fe3-4d58-8ffe-16755fcbc635', data: { message: 'Hello from @RailsEventStore!' })) event_store.publish(TweetRetweeted.new(event_id: '3d67e05d-04c6-4771-bdcc-d22d385390cb', data: { ... })) event_store.read.of_type([TweetPosted]).to_a # => [#<TweetPosted:0x00007fce3cab1a00 @event_id="54994b0e-4fe3-4d58-8ffe-16755fcbc635", @metadata=#<RubyEventStore::Metadata:0x00007fce3cab19b0 @h={:timestamp=>2018-10-12 17:50:27 UTC}>, @data={:message=>"Hello from @RailsEventStore!"}>] event_store.read.of_type([TweetLiked]).to_a # => []
-
Change:
RailsEventStore::Event#initializeno longer callsto_hondata:argument. Default value for this argument stays effectively the same (which is{}). One now has an option to pass struct or any other object asdata, provided your configured mapper knows how to handle it for serialization [#395, #480] -
Add: Bring back
RailsEventStore::Browser. This time not as a separate gem, rather a thin wrapper overRubyEventStore::Browser. It is no longer needed withrails_event_storeto add browser as an explicit dependency. As a bonusRailsEventStore::Browseralready hasevent_store_locator:pre-configured to typicalRails.configuration.event_store[#497]The whole process of mounting Browser in Rails is as simple as following:
Rails.application.routes.draw do mount RailsEventStore::Browser => '/res' if Rails.env.development? end
RubyEventStore
-
Add: New read API to filter read events by type
event_store.read.of_type[#472]event_store = RailsEventStore::Client.new TweetPosted = Class.new(RubyEventStore::Event) TweetRetweeted = Class.new(RubyEventStore::Event) TweetLiked = Class.new(RubyEventStore::Event) event_store.publish(TweetPosted.new(event_id: '54994b0e-4fe3-4d58-8ffe-16755fcbc635', data: { message: 'Hello from @RailsEventStore!' })) event_store.publish(TweetRetweeted.new(event_id: '3d67e05d-04c6-4771-bdcc-d22d385390cb', data: { ... })) event_store.read.of_type([TweetPosted]).to_a # => [#<TweetPosted:0x00007fce3cab1a00 @event_id="54994b0e-4fe3-4d58-8ffe-16755fcbc635", @metadata=#<RubyEventStore::Metadata:0x00007fce3cab19b0 @h={:timestamp=>2018-10-12 17:50:27 UTC}>, @data={:message=>"Hello from @RailsEventStore!"}>] event_store.read.of_type([TweetLiked]).to_a # => []
-
Fix: Do not compare object instances of event id while looking for streams of event [#492]
-
Fix:
read.events([])returning whole dataset of stored events [#498] -
Change:
RubyEventStore::Event#initializeno longer callsto_hondata:argument. Default value for this argument stays effectively the same (which is{}). One now has an option to pass struct or any other object asdata, provided your configured mapper knows how to handle it for serialization [#395, #480] -
Add: Explicit
RubyEventStore::ProtobufEncodingFailedraised when event'sdatais not serializable byRubyEventStore::Mappers::Protobuf[#481] -
Fix:
RubyEventStore::Mappers::Default#serialized_record_to_eventnow symbolizes metadata keys. This helps when your serializer cannot distinguish symbols from strings (i.e. when you chooseJSONas a serializer) [#367, #489]When using
RubyEventStore::Mappers::Default.new(serializer: JSON)it is advisable to make following or similar adjustment to your base Event class. That way you'll shield yourself fromJSONturning symbols intro strings:class MyEvent < RailsEventStore::Event def data ActiveSupport::HashWithIndifferentAccess.new(super) end end OrderPlaced = Class.new(MyEvent)
More on configuring a different serializer section.
RailsEventStoreActiveRecord
-
Add: Support for filtering by event type [#472]
-
Add: New migration generator to add an index on
event_typeattribute. Strongly recommended to apply if you plan to use filtering by event types — otherwise performance when usingevent_store.read.of_type(...)might be degraded. Added in default schema creation generator for new deployments. [#472]Running migration:
rails g rails_event_store_active_record:index_by_event_type rails db:migrateFeel free to inspect and change generated migration. Make sure to check if your RDBMS can run this migration online and whether that meets your operational requirements.
https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html#online-ddl-index-operations -
Add: New migration generator to add a limit on
event_idattribute inevent_store_events_in_streamstable. Applicable for MySQL and Sqlite databases. This migration is skipped on PostgreSQL. Feel free to skip this migration if it's too problematic to apply on existing data. Added in default schema creation generator for new deployments. [#479]Running migration:
rails g rails_event_store_active_record:limit_for_event_id rails db:migrateFeel free to inspect and change generated migration. Make sure to check if your RDBMS can run this migration online and whether that meets your operational requirements.
https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html#online-ddl-column-operations -
Add: to_a implementation for read specification. Allows to avoid commonly used
event_store.read.each.to_aby just usingevent_store.read.to_a. Also addedto_a&firstmethods toBatchEnumerator. Closes #496. [#499]
AggregateRoot
- no changes
RailsEventStore::RSpec
- no changes
BoundedContext
- no changes
RubyEventStore::Browser
-
Fix: Ensure Browser works with non-default metadata serialization [#491]
-
Change: Provide default arguments to
RubyEventStore::Browser::App.forfor less required setup in typical use case [#483]Now only
event_store_locator:is required when mounting Browser inside existing app.require 'ruby_event_store/browser/app' Rails.application.routes.draw do mount RubyEventStore::Browser::App.for( event_store_locator: -> { Rails.configuration.event_store }, ) => '/res' if Rails.env.development? end
RubyEventStore::ROM
- Support for filtering by event type [#472]
RailsEventStoreActiveRecord::Legacy
- Support for filtering by event type [#472]
v0.33.0
RailsEventStore
-
Remove: Deprecated
RailsEventStore::Client#publish_event,RailsEventStore::Client#publish_events,RailsEventStore::Client#link_to_streamandRailsEventStore::Client#append_to_streamare no more. -
Change: Less chatty
RailsEventStore::Clientinstance in console [#465]Please use
RailsEventStore::Client#publish,RailsEventStore::Client#linkandRailsEventStore::Client#appendinstead. -
Change: Unify read API further more by introducing
event_store.read.event,event_store.read.event!andevent_store.read.events. Deprecatesevent_store.read_event[#462]event_store = RailsEventStore::Client.new TweetPosted = Class.new(RubyEventStore::Event) event_store.publish(TweetPosted.new(event_id: '54994b0e-4fe3-4d58-8ffe-16755fcbc635', data: { message: 'Hello from @RailsEventStore!' })) event_store.read.event('54994b0e-4fe3-4d58-8ffe-16755fcbc635') # => #<TweetPosted:0x00007fce3cb166d0 @event_id="54994b0e-4fe3-4d58-8ffe-16755fcbc635", @metadata=#<RubyEventStore::Metadata:0x00007fce3cb16658 @h={:timestamp=>2018-10-12 17:50:27 UTC}>, @data={:message=>"Hello from @RailsEventStore!"}> event_store.read.event('54994b0e-4fe3-4d58-8ffe-xxxxx') # => nil event_store.read.event!('54994b0e-4fe3-4d58-8ffe-16755fcbc635') # => #<TweetPosted:0x00007fce3cb05498 @event_id="54994b0e-4fe3-4d58-8ffe-16755fcbc635", @metadata=#<RubyEventStore::Metadata:0x00007fce3cb05448 @h={:timestamp=>2018-10-12 17:50:27 UTC}>, @data={:message=>"Hello from @RailsEventStore!"}> event_store.read.event!('54994b0e-4fe3-4d58-8ffe-xxxxx') # => RailsEventStore::EventNotFound (Event not found: 54994b0e-4fe3-4d58-8ffe-xxxxx) event_store.read.events(['54994b0e-4fe3-4d58-8ffe-xxxxx', '54994b0e-4fe3-4d58-8ffe-16755fcbc635']).to_a # => [#<TweetPosted:0x00007fce3cab1a00 @event_id="54994b0e-4fe3-4d58-8ffe-16755fcbc635", @metadata=#<RubyEventStore::Metadata:0x00007fce3cab19b0 @h={:timestamp=>2018-10-12 17:50:27 UTC}>, @data={:message=>"Hello from @RailsEventStore!"}>]
RubyEventStore
-
Remove: Deprecated
RubyEventStore::Client#publish_event,RubyEventStore::Client#publish_events,RubyEventStore::Client#link_to_streamandRubyEventStore::Client#append_to_streamare no more.Please use
RubyEventStore::Client#publish,RubyEventStore::Client#linkandRubyEventStore::Client#appendinstead. -
Change: Less chatty
RubyEventStore::Clientinstance in console [#465] -
Change: Unify read API further more by introducing
event_store.read.event,event_store.read.event!andevent_store.read.events. Deprecatesevent_store.read_event[#462]event_store = RubyEventStore::Client.new(repository: RubyEventStore::InMemoryRepository.new) TweetPosted = Class.new(RubyEventStore::Event) event_store.publish(TweetPosted.new(event_id: '54994b0e-4fe3-4d58-8ffe-16755fcbc635', data: { message: 'Hello from @RailsEventStore!' })) event_store.read.event('54994b0e-4fe3-4d58-8ffe-16755fcbc635') # => #<TweetPosted:0x00007fce3cb166d0 @event_id="54994b0e-4fe3-4d58-8ffe-16755fcbc635", @metadata=#<RubyEventStore::Metadata:0x00007fce3cb16658 @h={:timestamp=>2018-10-12 17:50:27 UTC}>, @data={:message=>"Hello from @RailsEventStore!"}> event_store.read.event('54994b0e-4fe3-4d58-8ffe-xxxxx') # => nil event_store.read.event!('54994b0e-4fe3-4d58-8ffe-16755fcbc635') # => #<TweetPosted:0x00007fce3cb05498 @event_id="54994b0e-4fe3-4d58-8ffe-16755fcbc635", @metadata=#<RubyEventStore::Metadata:0x00007fce3cb05448 @h={:timestamp=>2018-10-12 17:50:27 UTC}>, @data={:message=>"Hello from @RailsEventStore!"}> event_store.read.event!('54994b0e-4fe3-4d58-8ffe-xxxxx') # => RubyEventStore::EventNotFound (Event not found: 54994b0e-4fe3-4d58-8ffe-xxxxx) event_store.read.events(['54994b0e-4fe3-4d58-8ffe-xxxxx', '54994b0e-4fe3-4d58-8ffe-16755fcbc635']).to_a # => [#<TweetPosted:0x00007fce3cab1a00 @event_id="54994b0e-4fe3-4d58-8ffe-16755fcbc635", @metadata=#<RubyEventStore::Metadata:0x00007fce3cab19b0 @h={:timestamp=>2018-10-12 17:50:27 UTC}>, @data={:message=>"Hello from @RailsEventStore!"}>]
RailsEventStoreActiveRecord
- Fix: Make sure legacy schema presence is not checked when
event_store_eventstable is not created yet. Improves situation when initializingRailsEventStore::EventRepositorywould prevent a migration to create such table to execute [#464]
AggregateRoot
- no changes
RailsEventStore::RSpec
- no changes
BoundedContext
- no changes
RubyEventStore::Browser
- no changes
Just a reminder that RailsEventStore::Browser is discontinued. RubyEventStore::Browser can do the same and works in and outside of Rails. Read more on enabling browser in docs
RubyEventStore::ROM
- no changes
RailsEventStoreActiveRecord::Legacy
- no changes