sequent 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/bin/sequent +65 -0
  3. data/db/sequent_schema.rb +9 -8
  4. data/lib/sequent.rb +3 -0
  5. data/lib/sequent/configuration.rb +67 -0
  6. data/lib/sequent/core/aggregate_repository.rb +1 -1
  7. data/lib/sequent/core/core.rb +2 -2
  8. data/lib/sequent/core/event_store.rb +2 -2
  9. data/lib/sequent/core/helpers/attribute_support.rb +3 -0
  10. data/lib/sequent/core/helpers/self_applier.rb +1 -1
  11. data/lib/sequent/core/{record_sessions/active_record_session.rb → persistors/active_record_persistor.rb} +21 -19
  12. data/lib/sequent/core/persistors/persistor.rb +84 -0
  13. data/lib/sequent/core/persistors/persistors.rb +3 -0
  14. data/lib/sequent/core/{record_sessions/replay_events_session.rb → persistors/replay_optimized_postgres_persistor.rb} +16 -7
  15. data/lib/sequent/core/projector.rb +96 -0
  16. data/lib/sequent/generator.rb +2 -0
  17. data/lib/sequent/generator/aggregate.rb +71 -0
  18. data/lib/sequent/generator/project.rb +61 -0
  19. data/lib/sequent/generator/template_aggregate/template_aggregate.rb +4 -0
  20. data/lib/sequent/generator/template_aggregate/template_aggregate/commands.rb +2 -0
  21. data/lib/sequent/generator/template_aggregate/template_aggregate/events.rb +2 -0
  22. data/lib/sequent/generator/template_aggregate/template_aggregate/template_aggregate.rb +9 -0
  23. data/lib/sequent/generator/template_aggregate/template_aggregate/template_aggregate_command_handler.rb +5 -0
  24. data/lib/sequent/generator/template_project/Gemfile +11 -0
  25. data/lib/sequent/generator/template_project/Gemfile.lock +72 -0
  26. data/lib/sequent/generator/template_project/Rakefile +12 -0
  27. data/lib/sequent/generator/template_project/app/projectors/post_projector.rb +22 -0
  28. data/lib/sequent/generator/template_project/app/records/post_record.rb +2 -0
  29. data/lib/sequent/generator/template_project/config/initializers/sequent.rb +13 -0
  30. data/lib/sequent/generator/template_project/db/database.yml +17 -0
  31. data/lib/sequent/generator/template_project/db/migrations.rb +17 -0
  32. data/lib/sequent/generator/template_project/db/sequent_schema.rb +51 -0
  33. data/lib/sequent/generator/template_project/db/tables/post_records.sql +10 -0
  34. data/lib/sequent/generator/template_project/lib/post.rb +4 -0
  35. data/lib/sequent/generator/template_project/lib/post/commands.rb +4 -0
  36. data/lib/sequent/generator/template_project/lib/post/events.rb +14 -0
  37. data/lib/sequent/generator/template_project/lib/post/post.rb +24 -0
  38. data/lib/sequent/generator/template_project/lib/post/post_command_handler.rb +5 -0
  39. data/lib/sequent/generator/template_project/my_app.rb +11 -0
  40. data/lib/sequent/generator/template_project/spec/app/projectors/post_projector_spec.rb +32 -0
  41. data/lib/sequent/generator/template_project/spec/lib/post/post_command_handler_spec.rb +20 -0
  42. data/lib/sequent/generator/template_project/spec/spec_helper.rb +29 -0
  43. data/lib/sequent/migrations/migrate_events.rb +1 -0
  44. data/lib/sequent/migrations/migrations.rb +2 -0
  45. data/lib/sequent/migrations/projectors.rb +18 -0
  46. data/lib/sequent/migrations/view_schema.rb +364 -0
  47. data/lib/sequent/rake/migration_tasks.rb +109 -0
  48. data/lib/sequent/rake/tasks.rb +16 -0
  49. data/lib/sequent/sequent.rb +53 -13
  50. data/lib/sequent/support/database.rb +53 -8
  51. data/lib/sequent/util/printer.rb +16 -0
  52. data/lib/sequent/util/timer.rb +14 -0
  53. data/lib/sequent/util/util.rb +2 -0
  54. data/lib/version.rb +1 -1
  55. metadata +67 -14
  56. data/lib/sequent/core/base_event_handler.rb +0 -54
  57. data/lib/sequent/core/record_sessions/record_sessions.rb +0 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 73d2ee9247b64d69617de99ffed129de86385e4a58f463b52d5558126ccf89ba
4
- data.tar.gz: 32b61b477f9a7ff2d0df8b93a7a704705a20b661cdeab3b9388431e4ec4b9d8d
3
+ metadata.gz: ee34fdc286ef0c550e0ccd50b64f1e726457c3e58e656797e84cb36bd9e36aa0
4
+ data.tar.gz: 77546ab25b533fc77ce08cfee7252df089362d533b52d2c09e885298e197c737
5
5
  SHA512:
6
- metadata.gz: 784e843cfc6a86120b9f48779fad3104d3504fd7d472ab925a19f0de897fd2b0f745d1fb4e8c77bcecbb254976e0148443d18bed52dabd8f9400cf1551c451d3
7
- data.tar.gz: 9f027d9bb65d643ecb5cf2b37c854890d4c3b3bba840373088e3a1b35db92de0d7f22bc76ebc92910d076e6ed102aba9d20fe96f5195e0e9ed3f36bd5a53ee4c
6
+ metadata.gz: 91d3d4c9e946d75488adf4e3b86fb20c99c90f4c324d3d29f276518357f5ec8ba2db12707f48ecf0a577eb15582dce38c01fd1a6885501faea1e1a384c967ccf
7
+ data.tar.gz: 007c283a04b967879769152a4e0b2e5f84b4571f64de751621e5337d75b39e17473be44f8a61358e3fcbfe8e73d9bec64c3d83b7d8d0823ebdf2e5740cb3f22c
data/bin/sequent ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/sequent/generator'
3
+
4
+ def new_project(args)
5
+ name, _ = args
6
+ abort('Please specify a directory name. i.e. `sequent new myapp`') if name.empty?
7
+
8
+ Sequent::Generator::Project.new(name).execute
9
+ puts <<~NEXTSTEPS
10
+
11
+ Success!
12
+
13
+ Your brand spanking new sequent app is waiting for you in:
14
+ #{File.expand_path(name, __dir__)}
15
+
16
+ To finish setting up your app:
17
+ cd #{name}
18
+ bundle install
19
+ bundle exec rake sequent:db:create
20
+ bundle exec rake sequent:migrate:online
21
+ bundle exec rake sequent:migrate:offline
22
+
23
+ Run the example specs:
24
+ RACK_ENV=test bundle exec rake sequent:db:create
25
+ bundle exec rspec spec
26
+
27
+ To generate new aggregates use:
28
+ sequent generate <aggregate_name>. e.g. sequent generate address
29
+
30
+ For more information see:
31
+ sequent.io
32
+
33
+ Happy coding!
34
+
35
+ NEXTSTEPS
36
+ end
37
+
38
+ def generate(args)
39
+ entity, _ = args
40
+ abort('Please specify a command. i.e. `sequent g aggregate user`') if entity.empty?
41
+
42
+ case entity
43
+ when 'aggregate'
44
+ _, aggregate_name = args
45
+ abort('Please specify a aggregate name. i.e. `sequent g aggregate user`') if !aggregate_name || aggregate_name.empty?
46
+
47
+ Sequent::Generator::Aggregate.new(aggregate_name).execute
48
+ puts "#{aggregate_name} aggregate has been generated"
49
+ else
50
+ abort("Unknown argument #{entity} for `generate`. Try `sequent g aggregate user`")
51
+ end
52
+ end
53
+
54
+ command = ARGV[0].to_s.strip
55
+ abort('Please specify a command. i.e. `sequent new myapp`') if command.empty?
56
+ args = ARGV[1..10].map(&:to_s).map(&:strip)
57
+
58
+ case command
59
+ when 'new'
60
+ new_project(args)
61
+ when 'generate', 'g'
62
+ generate(args)
63
+ else
64
+ abort("Unknown command #{command}. Try `sequent new myapp`")
65
+ end
data/db/sequent_schema.rb CHANGED
@@ -10,14 +10,6 @@ ActiveRecord::Schema.define do
10
10
  t.integer "stream_record_id", :null => false
11
11
  end
12
12
 
13
- create_table "command_records", :force => true do |t|
14
- t.string "user_id"
15
- t.string "aggregate_id"
16
- t.string "command_type", :null => false
17
- t.text "command_json", :null => false
18
- t.datetime "created_at", :null => false
19
- end
20
-
21
13
  execute %Q{
22
14
  CREATE UNIQUE INDEX unique_event_per_aggregate ON event_records (
23
15
  aggregate_id,
@@ -28,10 +20,19 @@ CREATE UNIQUE INDEX unique_event_per_aggregate ON event_records (
28
20
  execute %Q{
29
21
  CREATE INDEX snapshot_events ON event_records (aggregate_id, sequence_number DESC) WHERE event_type = 'Sequent::Core::SnapshotEvent'
30
22
  }
23
+
31
24
  add_index "event_records", ["command_record_id"], :name => "index_event_records_on_command_record_id"
32
25
  add_index "event_records", ["event_type"], :name => "index_event_records_on_event_type"
33
26
  add_index "event_records", ["created_at"], :name => "index_event_records_on_created_at"
34
27
 
28
+ create_table "command_records", :force => true do |t|
29
+ t.string "user_id"
30
+ t.string "aggregate_id"
31
+ t.string "command_type", :null => false
32
+ t.text "command_json", :null => false
33
+ t.datetime "created_at", :null => false
34
+ end
35
+
35
36
  create_table "stream_records", :force => true do |t|
36
37
  t.datetime "created_at", :null => false
37
38
  t.string "aggregate_type", :null => false
data/lib/sequent.rb CHANGED
@@ -1 +1,4 @@
1
1
  require_relative 'sequent/sequent'
2
+ require_relative 'sequent/core/core'
3
+ require_relative 'sequent/util/util'
4
+ require_relative 'sequent/migrations/migrations'
@@ -2,9 +2,28 @@ require_relative 'core/event_store'
2
2
  require_relative 'core/command_service'
3
3
  require_relative 'core/transactions/no_transactions'
4
4
  require_relative 'core/aggregate_repository'
5
+ require_relative 'core/persistors/active_record_persistor'
6
+ require 'logger'
5
7
 
6
8
  module Sequent
7
9
  class Configuration
10
+
11
+ DEFAULT_VERSIONS_TABLE_NAME = 'sequent_versions'
12
+ DEFAULT_REPLAYED_IDS_TABLE_NAME = 'sequent_replayed_ids'
13
+
14
+ DEFAULT_MIGRATION_SQL_FILES_DIRECTORY = 'db/tables'
15
+ DEFAULT_DATABASE_CONFIG_DIRECTORY = 'db'
16
+
17
+ DEFAULT_VIEW_SCHEMA_NAME = 'view_schema'
18
+ DEFAULT_EVENT_STORE_SCHEMA_NAME= 'sequent_schema'
19
+
20
+ MIGRATIONS_CLASS_NAME = 'Sequent::Migrations::Projectors'
21
+
22
+ DEFAULT_NUMBER_OF_REPLAY_PROCESSES = 4
23
+
24
+ DEFAULT_OFFLINE_REPLAY_PERSISTOR_CLASS = Sequent::Core::Persistors::ActiveRecordPersistor
25
+ DEFAULT_ONLINE_REPLAY_PERSISTOR_CLASS = Sequent::Core::Persistors::ActiveRecordPersistor
26
+
8
27
  attr_accessor :aggregate_repository
9
28
 
10
29
  attr_accessor :event_store,
@@ -24,6 +43,20 @@ module Sequent
24
43
 
25
44
  attr_accessor :disable_event_handlers
26
45
 
46
+ attr_accessor :logger
47
+
48
+ attr_accessor :migration_sql_files_directory,
49
+ :view_schema_name,
50
+ :offline_replay_persistor_class,
51
+ :online_replay_persistor_class,
52
+ :number_of_replay_processes,
53
+ :database_config_directory,
54
+ :event_store_schema_name
55
+
56
+ attr_reader :migrations_class_name,
57
+ :versions_table_name,
58
+ :replayed_ids_table_name
59
+
27
60
  def self.instance
28
61
  @instance ||= new
29
62
  end
@@ -51,6 +84,40 @@ module Sequent
51
84
  self.uuid_generator = Sequent::Core::RandomUuidGenerator
52
85
  self.event_publisher = Sequent::Core::EventPublisher.new
53
86
  self.disable_event_handlers = false
87
+ self.versions_table_name = DEFAULT_VERSIONS_TABLE_NAME
88
+ self.replayed_ids_table_name = DEFAULT_REPLAYED_IDS_TABLE_NAME
89
+ self.migration_sql_files_directory = DEFAULT_MIGRATION_SQL_FILES_DIRECTORY
90
+ self.view_schema_name = DEFAULT_VIEW_SCHEMA_NAME
91
+ self.event_store_schema_name = DEFAULT_EVENT_STORE_SCHEMA_NAME
92
+ self.migrations_class_name = MIGRATIONS_CLASS_NAME
93
+ self.number_of_replay_processes = DEFAULT_NUMBER_OF_REPLAY_PROCESSES
94
+
95
+ self.offline_replay_persistor_class = DEFAULT_OFFLINE_REPLAY_PERSISTOR_CLASS
96
+ self.online_replay_persistor_class = DEFAULT_ONLINE_REPLAY_PERSISTOR_CLASS
97
+ self.database_config_directory = DEFAULT_DATABASE_CONFIG_DIRECTORY
98
+
99
+ self.logger = Logger.new(STDOUT).tap {|l| l.level = Logger::INFO }
100
+ end
101
+
102
+ def replayed_ids_table_name=(table_name)
103
+ fail ArgumentError.new('table_name can not be nil') unless table_name
104
+
105
+ @replayed_ids_table_name = table_name
106
+ Sequent::Migrations::ViewSchema::ReplayedIds.table_name = table_name
107
+ end
108
+
109
+ def versions_table_name=(table_name)
110
+ fail ArgumentError.new('table_name can not be nil') unless table_name
111
+
112
+ @versions_table_name = table_name
113
+ Sequent::Migrations::ViewSchema::Versions.table_name = table_name
54
114
  end
115
+
116
+ def migrations_class_name=(class_name)
117
+ migration_class = Class.const_get(class_name)
118
+ fail ArgumentError.new("#{migration_class} must extend Sequent::Migrations::Projectors") unless migration_class <= Sequent::Migrations::Projectors
119
+ @migrations_class_name = class_name
120
+ end
121
+
55
122
  end
56
123
  end
@@ -10,7 +10,7 @@ module Sequent
10
10
  # queried for uncommitted events. After persisting these events
11
11
  # the uncommitted events are cleared from the aggregate.
12
12
  #
13
- # The repository is keeps track of the Unit-Of-Work per thread,
13
+ # The repository keeps track of the Unit-Of-Work per thread,
14
14
  # so can be shared between threads.
15
15
  class AggregateRepository
16
16
  # Key used in thread local
@@ -1,6 +1,6 @@
1
1
  require_relative 'sequent_oj'
2
2
  require_relative 'helpers/helpers'
3
- require_relative 'record_sessions/record_sessions'
3
+ require_relative 'persistors/persistors'
4
4
  require_relative 'transactions/transactions'
5
5
  require_relative 'event'
6
6
  require_relative 'aggregate_repository'
@@ -9,7 +9,7 @@ require_relative 'base_command_handler'
9
9
  require_relative 'command'
10
10
  require_relative 'command_service'
11
11
  require_relative 'value_object'
12
- require_relative 'base_event_handler'
12
+ require_relative 'projector'
13
13
  require_relative 'event_store'
14
14
  require_relative 'event_record'
15
15
  require_relative 'command_record'
@@ -119,9 +119,9 @@ ORDER BY sequence_number ASC, (CASE event_type WHEN #{quote Sequent.configuratio
119
119
 
120
120
  PRINT_PROGRESS = lambda do |progress, done, _|
121
121
  if done
122
- puts "Done replaying #{progress} events"
122
+ Sequent.logger.debug "Done replaying #{progress} events"
123
123
  else
124
- puts "Replayed #{progress} events"
124
+ Sequent.logger.debug "Replayed #{progress} events"
125
125
  end
126
126
  end
127
127
 
@@ -2,6 +2,9 @@ require 'active_support'
2
2
  require_relative '../ext/ext'
3
3
  require_relative 'array_with_type'
4
4
  require_relative 'default_validators'
5
+ require_relative 'type_conversion_support'
6
+ require_relative 'date_time_validator'
7
+ require_relative 'association_validator'
5
8
 
6
9
  module Sequent
7
10
  module Core
@@ -3,7 +3,7 @@ module Sequent
3
3
  module Helpers
4
4
  ##
5
5
  # Creates ability to use DSL like:
6
- # class MyEventHandler < Sequent::Core::BaseEventHandler
6
+ # class MyEventHandler < Sequent::Core::Projector
7
7
  #
8
8
  # on MyEvent do |event|
9
9
  # do_some_logic
@@ -1,15 +1,21 @@
1
1
  require 'active_record'
2
+ require_relative './persistor'
2
3
 
3
4
  module Sequent
4
5
  module Core
5
- module RecordSessions
6
+ module Persistors
6
7
 
7
8
  #
8
- # Session objects are used to update view state
9
+ # The ActiveRecordPersistor uses ActiveRecord to update the projection
9
10
  #
10
- # The ActiveRecordSession object can be used when you use ActiveRecord as view state store.
11
+ # This is the default persistor in Sequent, but when your event store
12
+ # is growing it is not the best choice as persistor while rebuilding
13
+ # a projection when migrating to a new version of that projection.
11
14
  #
12
- class ActiveRecordSession
15
+ # Please see the +ReplayOptimizedPostgresPersistor+ as alternative
16
+ # for migrating projections to a new version.
17
+ class ActiveRecordPersistor
18
+ include Persistor
13
19
 
14
20
  def update_record(record_class, event, where_clause = {aggregate_id: event.aggregate_id}, options = {}, &block)
15
21
  record = record_class.unscoped.where(where_clause).first
@@ -23,10 +29,6 @@ module Sequent
23
29
  record.save!
24
30
  end
25
31
 
26
- def execute(statement)
27
- ActiveRecord::Base.connection.execute(statement)
28
- end
29
-
30
32
  def create_record(record_class, values)
31
33
  record = new_record(record_class, values)
32
34
  yield record if block_given?
@@ -46,7 +48,7 @@ module Sequent
46
48
  insert_manager.to_sql
47
49
  end.join(";")
48
50
 
49
- execute(query)
51
+ execute_sql(query)
50
52
  end
51
53
 
52
54
  def create_or_update_record(record_class, values, created_at = Time.now)
@@ -101,6 +103,14 @@ module Sequent
101
103
  record_class.unscoped.where(where_clause).last
102
104
  end
103
105
 
106
+ def execute_sql(statement)
107
+ ActiveRecord::Base.connection.execute(statement)
108
+ end
109
+
110
+ def commit
111
+ # noop
112
+ end
113
+
104
114
  private
105
115
 
106
116
  def new_record(record_class, values)
@@ -108,19 +118,11 @@ module Sequent
108
118
  end
109
119
 
110
120
  def new_insert_manager
111
- if ActiveRecord::VERSION::MAJOR <= 4
112
- Arel::InsertManager.new(ActiveRecord::Base)
113
- else
114
- Arel::InsertManager.new
115
- end
121
+ Arel::InsertManager.new
116
122
  end
117
123
 
118
124
  def convert_to_values(key, table, value)
119
- if ActiveRecord::VERSION::MAJOR <= 4
120
- [table[key], value]
121
- else
122
- [table[key], table.type_cast_for_database(key, value)]
123
- end
125
+ [table[key], table.type_cast_for_database(key, value)]
124
126
  end
125
127
  end
126
128
  end
@@ -0,0 +1,84 @@
1
+ module Sequent
2
+ module Core
3
+ module Persistors
4
+ # Defines the methods that can be implemented by the specific +Persistors+
5
+ #
6
+ # See
7
+ # - +ActiveRecordPersistor+
8
+ # - +ReplayOptimizedPostgresPersistor+
9
+ module Persistor
10
+ # Updates the view state
11
+ def update_record
12
+ fail "Method not supported in this persistor"
13
+ end
14
+
15
+ # Create a single record in the view state
16
+ def create_record
17
+ fail "Method not supported in this persistor"
18
+ end
19
+
20
+ # Creates multiple records at once in the view state
21
+ def create_records
22
+ fail "Method not supported in this persistor"
23
+ end
24
+
25
+ # Creates or updates a record in the view state.
26
+ def create_or_update_record
27
+ fail "Method not supported in this persistor"
28
+ end
29
+ # Gets a record from the view state, fails if it not exists
30
+ def get_record!
31
+ fail "Method not supported in this persistor"
32
+ end
33
+
34
+ # Gets a record from the view state, returns +nil+ if it not exists
35
+ def get_record
36
+ fail "Method not supported in this persistor"
37
+ end
38
+
39
+ # Deletes all records given a where
40
+ def delete_all_records
41
+ fail "Method not supported in this persistor"
42
+ end
43
+
44
+ # Updates all record given a where and an update clause
45
+ def update_all_records
46
+ fail "Method not supported in this persistor"
47
+ end
48
+
49
+ # Decide for yourself what to do with the records
50
+ # @deprecated
51
+ def do_with_records
52
+ fail "Method not supported in this persistor"
53
+ end
54
+
55
+ # Decide for yourself what to do with a single record
56
+ # @deprecated
57
+ def do_with_record
58
+ fail "Method not supported in this persistor"
59
+ end
60
+
61
+ # Delete a single record
62
+ # @deprecated
63
+ def delete_record
64
+ fail "Method not supported in this persistor"
65
+ end
66
+
67
+ # Find records given a where
68
+ def find_records
69
+ fail "Method not supported in this persistor"
70
+ end
71
+
72
+ # Returns the last record given a where
73
+ def last_record
74
+ fail "Method not supported in this persistor"
75
+ end
76
+
77
+ # Hook to implement for instance the persistor batches statements
78
+ def commit
79
+ fail "Method not supported in this persistor"
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,3 @@
1
+ require_relative 'persistor'
2
+ require_relative 'active_record_persistor'
3
+ require_relative 'replay_optimized_postgres_persistor'
@@ -1,14 +1,22 @@
1
1
  require 'set'
2
2
  require 'active_record'
3
3
  require 'csv'
4
+ require_relative './persistor'
4
5
 
5
6
  module Sequent
6
7
  module Core
7
- module RecordSessions
8
+ module Persistors
8
9
  #
9
- # Session objects are used to update view state
10
+ # The ReplayOptimizedPostgresPersistor is optimized for bulk loading records in a Postgres database.
10
11
  #
11
- # The ReplayEventsSession is optimized for bulk loading records in a Postgres database using CSV import.
12
+ # Depending on the amount of records it uses CSV import, otherwise statements are batched
13
+ # using normal sql.
14
+ #
15
+ # Rebuilding the view state (or projection) of an aggregate typically consists
16
+ # of an initial insert and then many updates and maybe a delete. With a normal Persistor (like ActiveRecordPersistor)
17
+ # each action is executed to the database. This persitor creates an inmemory store first and finally flushes
18
+ # the in memory store to the database. This can significantly reduces the amount of queries to the database.
19
+ # E.g. 1 insert, 6 updates is only a single insert using this Persistor.
12
20
  #
13
21
  # After lot of experimenting this turned out to be the fastest way to to bulk inserts in the database.
14
22
  # You can tweak the amount of records in the CSV via +insert_with_csv_size+ before
@@ -19,7 +27,7 @@ module Sequent
19
27
  #
20
28
  # Example:
21
29
  #
22
- # class InvoiceEventHandler < Sequent::Core::Projector
30
+ # class InvoiceProjector < Sequent::Core::Projector
23
31
  # on RecipientMovedEvent do |event|
24
32
  # update_all_records InvoiceRecord, recipient_id: event.recipient.aggregate_id do |record|
25
33
  # record.recipient_street = record.recipient.street
@@ -31,11 +39,12 @@ module Sequent
31
39
  #
32
40
  # Example:
33
41
  #
34
- # ReplayEventsSession.new(
42
+ # ReplayOptimizedPostgresPersistor.new(
35
43
  # 50,
36
44
  # {InvoiceRecord => [[:recipient_id]]}
37
45
  # )
38
- class ReplayEventsSession
46
+ class ReplayOptimizedPostgresPersistor
47
+ include Persistor
39
48
 
40
49
  attr_reader :record_store
41
50
  attr_accessor :insert_with_csv_size
@@ -186,7 +195,7 @@ module Sequent
186
195
  end
187
196
  EOD
188
197
  eval("#{class_def}")
189
- struct_class = ReplayEventsSession.const_get(struct_class_name)
198
+ struct_class = ReplayOptimizedPostgresPersistor.const_get(struct_class_name)
190
199
  self.class.struct_cache[struct_class_name] = struct_class
191
200
  end
192
201
  record = struct_class.new.set_values(values)