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
@@ -0,0 +1,96 @@
1
+ require_relative 'helpers/self_applier'
2
+ require_relative './persistors/active_record_persistor'
3
+
4
+ module Sequent
5
+ module Core
6
+
7
+ module Migratable
8
+ module ClassMethods
9
+ def manages_tables(*tables)
10
+ @managed_tables = tables
11
+ end
12
+
13
+ def managed_tables
14
+ @managed_tables
15
+ end
16
+ end
17
+
18
+ def self.projectors
19
+ Sequent.configuration.event_handlers.select { |x| x.is_a? Migratable }.map(&:class)
20
+ end
21
+
22
+ def self.included(host_class)
23
+ host_class.extend(ClassMethods)
24
+ end
25
+
26
+ def self.none
27
+ []
28
+ end
29
+
30
+ def self.all
31
+ Migratable.projectors
32
+ end
33
+
34
+ def managed_tables
35
+ self.class.managed_tables
36
+ end
37
+
38
+ end
39
+
40
+ # Projectors listen to events and update the view state as they see fit.
41
+ #
42
+ # Example of updating view state, in this case the InvoiceRecord table representing an Invoice
43
+ #
44
+ # class InvoiceProjector < Sequent::Core::Projector
45
+ # on InvoiceCreated do |event|
46
+ # create_record(
47
+ # InvoiceRecord,
48
+ # recipient: event.recipient,
49
+ # amount: event.amount
50
+ # )
51
+ # end
52
+ # end
53
+ #
54
+ # Please note that the actual storage is abstracted away in the +persistors+.
55
+ # Due to this abstraction you can not traverse persist or traverse child objects
56
+ # like you are used to do with ActiveRecord. The following example will not work:
57
+ #
58
+ # invoice_record.line_item_records << create_record(LineItemRecord, ...)
59
+ #
60
+ # In this case you should simply do:
61
+ #
62
+ # create_record(LineItemRecord, invoice_id: invoice_record.aggregate_id)
63
+ #
64
+ class Projector
65
+ extend Forwardable
66
+ include Helpers::SelfApplier
67
+ include Migratable
68
+
69
+ def initialize(persistor = Sequent::Core::Persistors::ActiveRecordPersistor.new)
70
+ @persistor = persistor
71
+ end
72
+
73
+ def self.replay_persistor
74
+ nil
75
+ end
76
+
77
+ def_delegators :@persistor,
78
+ :update_record,
79
+ :create_record,
80
+ :create_records,
81
+ :create_or_update_record,
82
+ :get_record!,
83
+ :get_record,
84
+ :delete_all_records,
85
+ :update_all_records,
86
+ :do_with_records,
87
+ :do_with_record,
88
+ :delete_record,
89
+ :find_records,
90
+ :last_record,
91
+ :execute_sql,
92
+ :commit
93
+
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,2 @@
1
+ require_relative './generator/project'
2
+ require_relative './generator/aggregate'
@@ -0,0 +1,71 @@
1
+ require 'fileutils'
2
+ require 'active_support'
3
+ require 'active_support/core_ext/string'
4
+
5
+ class TargetAlreadyExists < StandardError; end
6
+
7
+ module Sequent
8
+ module Generator
9
+ class Aggregate
10
+ attr_reader :name
11
+
12
+ def initialize(name)
13
+ @name = name
14
+ end
15
+
16
+ def execute
17
+ ensure_not_used!
18
+ copy_files
19
+ rename_files
20
+ replace_template_aggregate
21
+ end
22
+
23
+ private
24
+
25
+ def copy_files
26
+ FileUtils.copy_entry(File.expand_path('template_aggregate', __dir__), path)
27
+ end
28
+
29
+ def rename_files
30
+ FileUtils.mv("#{path}/template_aggregate.rb", "#{path}/#{name_underscored}.rb")
31
+ FileUtils.mv("#{path}/template_aggregate", "#{path}/#{name_underscored}")
32
+
33
+ FileUtils.mv("#{path}/#{name_underscored}/template_aggregate_command_handler.rb", "#{path}/#{name_underscored}/#{name_underscored}_command_handler.rb")
34
+ FileUtils.mv("#{path}/#{name_underscored}/template_aggregate.rb", "#{path}/#{name_underscored}/#{name_underscored}.rb")
35
+ end
36
+
37
+ def replace_template_aggregate
38
+ files = Dir["#{path}/**/*"].select { |f| File.file?(f) }
39
+
40
+ files.each do |filename|
41
+ contents = File.read(filename)
42
+ contents.gsub!('template_aggregate', name_underscored)
43
+ contents.gsub!('TemplateAggregate', name_camelized)
44
+ File.open(filename, 'w') { |f| f.puts contents }
45
+ end
46
+ end
47
+
48
+ def path
49
+ @path ||= File.expand_path("lib")
50
+ end
51
+
52
+ def name
53
+ @name ||= File.basename(path)
54
+ end
55
+
56
+ def name_underscored
57
+ @name_underscored ||= name.underscore
58
+ end
59
+
60
+ def name_camelized
61
+ @name_camelized ||= name.camelize
62
+ end
63
+
64
+ def ensure_not_used!
65
+ if File.directory?("#{path}/#{name_underscored}") || File.exist?("#{path}/#{name_underscored}.rb")
66
+ raise TargetAlreadyExists
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,61 @@
1
+ require 'fileutils'
2
+ require 'active_support'
3
+ require 'active_support/core_ext/string'
4
+
5
+ module Sequent
6
+ module Generator
7
+ class Project
8
+ def initialize(path_or_name)
9
+ @path_or_name = path_or_name
10
+ end
11
+
12
+ def execute
13
+ make_directory
14
+ copy_files
15
+ rename_app_file
16
+ replace_app_name
17
+ end
18
+
19
+ private
20
+
21
+ def make_directory
22
+ FileUtils.mkdir_p(path)
23
+ end
24
+
25
+ def copy_files
26
+ FileUtils.copy_entry(File.expand_path('template_project', __dir__), path)
27
+ end
28
+
29
+ def rename_app_file
30
+ FileUtils.mv("#{path}/my_app.rb", "#{path}/#{name_underscored}.rb")
31
+ end
32
+
33
+ def replace_app_name
34
+ files = Dir["#{path}/**/*"].select { |f| File.file?(f) }
35
+
36
+ files.each do |filename|
37
+ contents = File.read(filename)
38
+ contents.gsub!('my_app', name_underscored)
39
+ contents.gsub!('MyApp', name_camelized)
40
+ File.open(filename, 'w') { |f| f.puts contents }
41
+ end
42
+ end
43
+
44
+ def path
45
+ @path ||= File.expand_path(@path_or_name)
46
+ end
47
+
48
+ def name
49
+ @name ||= File.basename(path)
50
+ end
51
+
52
+ def name_underscored
53
+ @name_underscored ||= name.underscore
54
+ end
55
+
56
+ def name_camelized
57
+ @name_camelized ||= name.camelize
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,4 @@
1
+ require_relative 'template_aggregate/commands'
2
+ require_relative 'template_aggregate/events'
3
+ require_relative 'template_aggregate/template_aggregate'
4
+ require_relative 'template_aggregate/template_aggregate_command_handler'
@@ -0,0 +1,2 @@
1
+ class AddTemplateAggregate < Sequent::Command
2
+ end
@@ -0,0 +1,2 @@
1
+ class TemplateAggregateAdded < Sequent::Event
2
+ end
@@ -0,0 +1,9 @@
1
+ class TemplateAggregate < Sequent::AggregateRoot
2
+ def initialize(command)
3
+ super(command.aggregate_id)
4
+ apply TemplateAggregateAdded
5
+ end
6
+
7
+ on TemplateAggregateAdded do
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class TemplateAggregateCommandHandler < Sequent::CommandHandler
2
+ on AddTemplateAggregate do |command|
3
+ repository.add_aggregate TemplateAggregate.new(command)
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org"
2
+ ruby "2.5.1"
3
+
4
+ gem 'rake'
5
+ # let's use the latest and greatest
6
+ gem 'sequent', git: 'https://github.com/zilverline/sequent', branch: 'sequent-30'
7
+
8
+ group :test do
9
+ gem 'rspec'
10
+ gem 'database_cleaner'
11
+ end
@@ -0,0 +1,72 @@
1
+ GIT
2
+ remote: https://github.com/zilverline/sequent
3
+ revision: 1e1066279c49d58adbb24f1a1d0e0a7e7bd10a55
4
+ branch: sequent-30
5
+ specs:
6
+ sequent (2.0.0)
7
+ activemodel (>= 5.0, < 5.2)
8
+ activerecord (>= 5.0, < 5.2)
9
+ oj (~> 3.3.9)
10
+ parallel (~> 1.12.1)
11
+ pg (~> 1.0)
12
+ postgresql_cursor (~> 0.6)
13
+ thread_safe (~> 0.3.5)
14
+
15
+ GEM
16
+ remote: https://rubygems.org/
17
+ specs:
18
+ activemodel (5.1.6)
19
+ activesupport (= 5.1.6)
20
+ activerecord (5.1.6)
21
+ activemodel (= 5.1.6)
22
+ activesupport (= 5.1.6)
23
+ arel (~> 8.0)
24
+ activesupport (5.1.6)
25
+ concurrent-ruby (~> 1.0, >= 1.0.2)
26
+ i18n (>= 0.7, < 2)
27
+ minitest (~> 5.1)
28
+ tzinfo (~> 1.1)
29
+ arel (8.0.0)
30
+ concurrent-ruby (1.0.5)
31
+ database_cleaner (1.7.0)
32
+ diff-lcs (1.3)
33
+ i18n (1.0.1)
34
+ concurrent-ruby (~> 1.0)
35
+ minitest (5.11.3)
36
+ oj (3.3.10)
37
+ parallel (1.12.1)
38
+ pg (1.0.0)
39
+ postgresql_cursor (0.6.1)
40
+ activerecord (>= 3.1.0)
41
+ rake (12.3.1)
42
+ rspec (3.7.0)
43
+ rspec-core (~> 3.7.0)
44
+ rspec-expectations (~> 3.7.0)
45
+ rspec-mocks (~> 3.7.0)
46
+ rspec-core (3.7.1)
47
+ rspec-support (~> 3.7.0)
48
+ rspec-expectations (3.7.0)
49
+ diff-lcs (>= 1.2.0, < 2.0)
50
+ rspec-support (~> 3.7.0)
51
+ rspec-mocks (3.7.0)
52
+ diff-lcs (>= 1.2.0, < 2.0)
53
+ rspec-support (~> 3.7.0)
54
+ rspec-support (3.7.1)
55
+ thread_safe (0.3.6)
56
+ tzinfo (1.2.5)
57
+ thread_safe (~> 0.1)
58
+
59
+ PLATFORMS
60
+ ruby
61
+
62
+ DEPENDENCIES
63
+ database_cleaner
64
+ rake
65
+ rspec
66
+ sequent!
67
+
68
+ RUBY VERSION
69
+ ruby 2.5.1p57
70
+
71
+ BUNDLED WITH
72
+ 1.16.2
@@ -0,0 +1,12 @@
1
+ ENV['RACK_ENV'] ||= 'development'
2
+
3
+ require './my_app'
4
+ require 'sequent/rake/migration_tasks'
5
+
6
+ Sequent::Rake::MigrationTasks.new.register_tasks!
7
+
8
+ task "sequent:migrate:init" => [:db_connect]
9
+
10
+ task "db_connect" do
11
+ Sequent::Support::Database.connect!(ENV['RACK_ENV'])
12
+ end
@@ -0,0 +1,22 @@
1
+ require_relative '../records/post_record'
2
+ require_relative '../../lib/post/events'
3
+
4
+ class PostProjector < Sequent::Projector
5
+ manages_tables PostRecord
6
+
7
+ on PostAdded do |event|
8
+ create_record(PostRecord, aggregate_id: event.aggregate_id)
9
+ end
10
+
11
+ on PostAuthorChanged do |event|
12
+ update_all_records(PostRecord, {aggregate_id: event.aggregate_id}, event.attributes.slice(:author))
13
+ end
14
+
15
+ on PostTitleChanged do |event|
16
+ update_all_records(PostRecord, {aggregate_id: event.aggregate_id}, event.attributes.slice(:title))
17
+ end
18
+
19
+ on PostContentChanged do |event|
20
+ update_all_records(PostRecord, {aggregate_id: event.aggregate_id}, event.attributes.slice(:content))
21
+ end
22
+ end
@@ -0,0 +1,2 @@
1
+ class PostRecord < ActiveRecord::Base
2
+ end
@@ -0,0 +1,13 @@
1
+ require './db/migrations'
2
+
3
+ Sequent.configure do |config|
4
+ config.migrations_class_name = 'Migrations'
5
+
6
+ config.command_handlers = [
7
+ PostCommandHandler.new
8
+ ]
9
+
10
+ config.event_handlers = [
11
+ PostProjector.new
12
+ ]
13
+ end
@@ -0,0 +1,17 @@
1
+ database: &database
2
+ adapter: postgresql
3
+ host: localhost
4
+ port: 5432
5
+ timeout: 5000
6
+ schema_search_path: "sequent_schema, view_schema"
7
+
8
+ development:
9
+ <<: *database
10
+ pool: 5
11
+ database: my_app_development
12
+
13
+ test:
14
+ <<: *database
15
+ pool: 5
16
+ database: my_app_test
17
+
@@ -0,0 +1,17 @@
1
+ require 'sequent/migrations/projectors'
2
+
3
+ VIEW_SCHEMA_VERSION = 1
4
+
5
+ class Migrations < Sequent::Migrations::Projectors
6
+ def self.version
7
+ VIEW_SCHEMA_VERSION
8
+ end
9
+
10
+ def self.versions
11
+ {
12
+ '1' => [
13
+ PostProjector
14
+ ]
15
+ }
16
+ end
17
+ end