diff --git a/.mutant.yml b/.mutant.yml index ce348a0..7449efd 100644 --- a/.mutant.yml +++ b/.mutant.yml @@ -5,6 +5,7 @@ includes: requires: - sequel - active_record +- connection_pool - en57 integration: name: minitest @@ -12,4 +13,8 @@ matcher: subjects: - En57* ignore: + - En57::EventStore.for_active_record + - En57::EventStore.for_pg + - En57::EventStore.for_pooled_pg + - En57::EventStore.for_sequel - En57::JsonSerializer#optional_big_decimal_type diff --git a/README.md b/README.md index dbbbd7c..0e14779 100644 --- a/README.md +++ b/README.md @@ -6,50 +6,30 @@ DCB-compatible event store library in Ruby with support for PostgreSQL. ### Connect with raw pg -Use `PgAdapter` when your app already owns a pg connection or connection pool. +Use `EventStore.for_pg` when En57 should own a pg connection. ```ruby -pool = ConnectionPool.new(size: 8) { PG.connect("postgres://localhost:5432/en57") } - -store = - En57::EventStore.new( - En57::Repository.new( - En57::PgAdapter.new(pool), - En57::JsonSerializer.new, - ), - ) +store = En57::EventStore.for_pg("postgres://localhost:5432/en57") ``` ### Connect with Sequel -Use `SequelAdapter` when your app already owns a Sequel database. +Use `EventStore.for_sequel` when your app already owns a Sequel database. ```ruby database = Sequel.connect("postgres://localhost:5432/en57") -store = - En57::EventStore.new( - En57::Repository.new( - En57::SequelAdapter.new(database), - En57::JsonSerializer.new, - ), - ) +store = En57::EventStore.for_sequel(database) ``` ### Connect with ActiveRecord -Use `ActiveRecordAdapter` when your app already owns an ActiveRecord pool. +Use `EventStore.for_active_record` when your app uses ActiveRecord. ```ruby ActiveRecord::Base.establish_connection("postgres://localhost:5432/en57") -store = - En57::EventStore.new( - En57::Repository.new( - En57::ActiveRecordAdapter.new(ActiveRecord::Base.connection_pool), - En57::JsonSerializer.new, - ), - ) +store = En57::EventStore.for_active_record ``` ### Append events unconditionally diff --git a/lib/en57/active_record_adapter.rb b/lib/en57/active_record_adapter.rb index 522d328..1962aba 100644 --- a/lib/en57/active_record_adapter.rb +++ b/lib/en57/active_record_adapter.rb @@ -22,4 +22,15 @@ module En57 end end end + + class EventStore + def self.for_active_record(model = ActiveRecord::Base) + new( + Repository.new( + ActiveRecordAdapter.new(model.connection_pool), + JsonSerializer.new, + ), + ) + end + end end diff --git a/lib/en57/pg_adapter.rb b/lib/en57/pg_adapter.rb index 5549680..e51efc3 100644 --- a/lib/en57/pg_adapter.rb +++ b/lib/en57/pg_adapter.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "pg" + module En57 class PgAdapter def initialize(connection_or_pool) @@ -26,4 +28,27 @@ module En57 end end end + + class EventStore + def self.for_pg(connection_uri) + new(Repository.new(PgAdapter.new(PG.connect(connection_uri)), JsonSerializer.new)) + end + end + + if defined?(ConnectionPool) + class EventStore + def self.for_pooled_pg(connection_uri, max_connections: 5) + new( + Repository.new( + PgAdapter.new( + ConnectionPool.new(size: max_connections) do + PG.connect(connection_uri) + end, + ), + JsonSerializer.new, + ), + ) + end + end + end end diff --git a/lib/en57/sequel_adapter.rb b/lib/en57/sequel_adapter.rb index 5064c3f..ea4565c 100644 --- a/lib/en57/sequel_adapter.rb +++ b/lib/en57/sequel_adapter.rb @@ -21,4 +21,10 @@ module En57 raise e.wrapped_exception end end + + class EventStore + def self.for_sequel(database) + new(Repository.new(SequelAdapter.new(database), JsonSerializer.new)) + end + end end diff --git a/test/test_factories.rb b/test/test_factories.rb new file mode 100644 index 0000000..6dcccbc --- /dev/null +++ b/test/test_factories.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require "test_helper" + +module En57 + class TestFactories < IntegrationTest + def test_for_pg_round_trips_with_connection_uri + assert_round_trip EventStore.for_pg(SERVER.url) + end + + def test_for_pooled_pg_round_trips_with_default_max_connections + assert_round_trip EventStore.for_pooled_pg(SERVER.url) + end + + def test_for_pooled_pg_round_trips_with_custom_max_connections + assert_round_trip EventStore.for_pooled_pg(SERVER.url, max_connections: 1) + end + + def test_for_active_record_round_trips_with_default_model + assert_round_trip EventStore.for_active_record + end + + def test_for_active_record_round_trips_with_custom_model + with_const(:DasModel, Class.new(ActiveRecord::Base)) do + assert_round_trip(EventStore.for_active_record(DasModel)) + end + end + + def test_for_sequel_round_trips_with_database + assert_round_trip EventStore.for_sequel(SEQUEL_DB) + end + + private + + def with_const(name, value) + Object.const_set(name, value) + yield + ensure + Object.__send__(:remove_const, name) + end + + def assert_round_trip(event_store) + event = Event.new(type: "FactoryTested") + + assert_equal [event], event_store.append([event]).read.each.to_a + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index efa3ef8..83db374 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -4,12 +4,16 @@ require "minitest/autorun" require "minitest/mock" require "mutant/minitest/coverage" +# optional dependencies require "sequel" require "active_record" +require "connection_pool" + require "en57" + +# test dependencies require "securerandom" require "concurrent-ruby" -require "connection_pool" require "pg_ephemeral" module En57