ruby_event_store-rom 0.35.0 → 0.36.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/.rubocop_todo.yml +84 -0
  4. data/Gemfile +4 -4
  5. data/Makefile +3 -0
  6. data/Rakefile +3 -3
  7. data/db/migrate/20180327044629_create_ruby_event_store_tables.rb +17 -8
  8. data/lib/ruby_event_store/rom.rb +19 -16
  9. data/lib/ruby_event_store/rom/adapters/memory/changesets/create_events.rb +17 -0
  10. data/lib/ruby_event_store/rom/adapters/memory/changesets/create_stream_entries.rb +17 -0
  11. data/lib/ruby_event_store/rom/adapters/memory/changesets/update_events.rb +16 -0
  12. data/lib/ruby_event_store/rom/adapters/memory/relations/events.rb +14 -5
  13. data/lib/ruby_event_store/rom/adapters/memory/relations/stream_entries.rb +8 -4
  14. data/lib/ruby_event_store/rom/adapters/memory/unit_of_work.rb +6 -21
  15. data/lib/ruby_event_store/rom/adapters/sql/changesets/create_events.rb +13 -0
  16. data/lib/ruby_event_store/rom/adapters/sql/changesets/update_events.rb +39 -0
  17. data/lib/ruby_event_store/rom/adapters/sql/index_violation_detector.rb +15 -16
  18. data/lib/ruby_event_store/rom/adapters/sql/relations/events.rb +13 -1
  19. data/lib/ruby_event_store/rom/adapters/sql/relations/stream_entries.rb +8 -4
  20. data/lib/ruby_event_store/rom/adapters/sql/tasks/migration_tasks.rake +16 -3
  21. data/lib/ruby_event_store/rom/changesets/create_events.rb +29 -0
  22. data/lib/ruby_event_store/rom/changesets/create_stream_entries.rb +21 -0
  23. data/lib/ruby_event_store/rom/changesets/update_events.rb +29 -0
  24. data/lib/ruby_event_store/rom/event_repository.rb +16 -6
  25. data/lib/ruby_event_store/rom/mappers/event_to_serialized_record.rb +1 -1
  26. data/lib/ruby_event_store/rom/mappers/stream_entry_to_serialized_record.rb +1 -1
  27. data/lib/ruby_event_store/rom/memory.rb +15 -3
  28. data/lib/ruby_event_store/rom/repositories/events.rb +18 -30
  29. data/lib/ruby_event_store/rom/repositories/stream_entries.rb +17 -18
  30. data/lib/ruby_event_store/rom/sql.rb +62 -12
  31. data/lib/ruby_event_store/rom/types.rb +13 -0
  32. data/lib/ruby_event_store/rom/unit_of_work.rb +1 -1
  33. data/lib/ruby_event_store/rom/version.rb +1 -1
  34. data/lib/ruby_event_store/spec/rom/event_repository_lint.rb +55 -90
  35. data/lib/ruby_event_store/spec/rom/relations/events_lint.rb +12 -12
  36. data/lib/ruby_event_store/spec/rom/relations/stream_entries_lint.rb +44 -44
  37. data/lib/ruby_event_store/spec/rom/spec_helper_lint.rb +1 -1
  38. data/lib/ruby_event_store/spec/rom/unit_of_work_lint.rb +1 -1
  39. data/ruby_event_store-rom.gemspec +12 -13
  40. metadata +40 -31
  41. data/lib/ruby_event_store/rom/adapters/sql/unit_of_work.rb +0 -37
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3760c9bc0e5cbf84b824cab9d38fc9ab85db2aea9fca8cc1ead956a67504d08f
4
- data.tar.gz: 520f6ee4fee9f63018c547276691f1c9b2c23ae55dd5384279d55302f2c7d3e8
3
+ metadata.gz: b0657b44931013a36c0db15e739957207921bc1344dceffd3046c6ab7636de06
4
+ data.tar.gz: 52a47bed2d4bd98d83928a28f26e85446b7c1ee3cf574f30cbe773dd8ca08071
5
5
  SHA512:
6
- metadata.gz: df638ec5c1bbb2ec850675769b601df6660c89ce5c1b98cef2a7fe3c05065c86c3176163d2fbd3eddaab116e6d63656a95e711a65acc75877e027ec9194e77f3
7
- data.tar.gz: b1df8c60802b4cd81e564da16f707d2b6baa3929507d072c94a7c29196789954150073a4d1b3d2f766663b7c74ddc2a18c1bdc1a92be6f065e9330e164bed23c
6
+ metadata.gz: 89d84ef8613d86632e570c0179ee3ef273eecd73c0f0e9779e237b0512c0d7690a44a958e5feccf34191bbbfddd10d4f479a520d96d450bf40506483db6a398a
7
+ data.tar.gz: bc6bfc3cc17b4568b172f15eae603a888d0dcdfbd019a5b5b9620cde86a09c5f1511dbe7ee96611674fa6e175a0008ee59554ce90f3bdefba3fe3ab8f61706f0
@@ -0,0 +1 @@
1
+ inherit_from: .rubocop_todo.yml
@@ -0,0 +1,84 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2018-12-29 04:25:35 -0500 using RuboCop version 0.61.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 3
10
+ Lint/HandleExceptions:
11
+ Exclude:
12
+ - 'Rakefile'
13
+ - 'lib/ruby_event_store/rom.rb'
14
+ - 'spec/spec_helper.rb'
15
+
16
+ # Offense count: 6
17
+ Metrics/AbcSize:
18
+ Max: 34
19
+
20
+ # Offense count: 8
21
+ # Configuration parameters: CountComments, ExcludedMethods.
22
+ # ExcludedMethods: refine
23
+ Metrics/BlockLength:
24
+ Max: 146
25
+
26
+ # Offense count: 2
27
+ Metrics/CyclomaticComplexity:
28
+ Max: 8
29
+
30
+ # Offense count: 6
31
+ # Configuration parameters: CountComments, ExcludedMethods.
32
+ Metrics/MethodLength:
33
+ Max: 30
34
+
35
+ # Offense count: 1
36
+ # Configuration parameters: CountComments.
37
+ Metrics/ModuleLength:
38
+ Max: 130
39
+
40
+ # Offense count: 2
41
+ Metrics/PerceivedComplexity:
42
+ Max: 11
43
+
44
+ # Offense count: 1
45
+ # Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
46
+ # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
47
+ Naming/FileName:
48
+ Exclude:
49
+ - 'lib/ruby_event_store-rom.rb'
50
+
51
+ # Offense count: 3
52
+ # Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist, MethodDefinitionMacros.
53
+ # NamePrefix: is_, has_, have_
54
+ # NamePrefixBlacklist: is_, has_, have_
55
+ # NameWhitelist: is_a?
56
+ # MethodDefinitionMacros: define_method, define_singleton_method
57
+ Naming/PredicateName:
58
+ Exclude:
59
+ - 'spec/**/*'
60
+ - 'lib/ruby_event_store/rom/event_repository.rb'
61
+ - 'lib/ruby_event_store/rom/memory.rb'
62
+ - 'lib/ruby_event_store/rom/sql.rb'
63
+
64
+ # Offense count: 16
65
+ # Cop supports --auto-correct.
66
+ # Configuration parameters: AutoCorrect, EnforcedStyle.
67
+ # SupportedStyles: nested, compact
68
+ Style/ClassAndModuleChildren:
69
+ Enabled: false
70
+
71
+ # Offense count: 25
72
+ Style/Documentation:
73
+ Enabled: false
74
+
75
+ # Offense count: 2
76
+ Style/MultilineBlockChain:
77
+ Exclude:
78
+ - 'spec/rom/adapters/memory/relations/stream_entries_spec.rb'
79
+
80
+ # Offense count: 136
81
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
82
+ # URISchemes: http, https
83
+ Metrics/LineLength:
84
+ Max: 151
data/Gemfile CHANGED
@@ -3,9 +3,9 @@ gemspec
3
3
 
4
4
  eval_gemfile File.expand_path('../lib/Gemfile.shared', __dir__)
5
5
 
6
+ gem 'childprocess'
7
+ gem 'fakefs', '~> 0.11.2'
8
+ gem 'mysql2', '>= 0.4.10'
9
+ gem 'pg', '>= 0.21'
6
10
  gem 'ruby_event_store', path: '../ruby_event_store'
7
11
  gem 'sqlite3', '1.3.13'
8
- gem 'pg', '>= 0.21'
9
- gem 'mysql2', '>= 0.4.10'
10
- gem 'fakefs', '~> 0.11.2'
11
- gem 'childprocess'
data/Makefile CHANGED
@@ -8,6 +8,9 @@ IGNORE = RubyEventStore::ROM::EventRepository\#initialize \
8
8
  RubyEventStore::ROM::EventRepository\#last_stream_event \
9
9
  RubyEventStore::ROM::Repositories::Events\#find_nonexistent_pks \
10
10
  RubyEventStore::ROM::Repositories::StreamEntries\#create_changeset \
11
+ RubyEventStore::ROM::Changesets::CreateStreamEntries::Defaults.included \
12
+ RubyEventStore::ROM::Changesets::CreateEvents::Defaults.included \
13
+ RubyEventStore::ROM::Changesets::UpdateEvents::Defaults.included \
11
14
  RubyEventStore::ROM::Env\#handle_error \
12
15
  RubyEventStore::ROM::Env\#initialize \
13
16
  RubyEventStore::ROM::Env\#register_error_handler \
data/Rakefile CHANGED
@@ -5,16 +5,16 @@ require 'ruby_event_store/rom/adapters/sql/rake_task'
5
5
  RSpec::Core::RakeTask.new(:spec)
6
6
  task default: [:ci]
7
7
 
8
- desc "Run CI tasks"
8
+ desc 'Run CI tasks'
9
9
  task ci: [:spec]
10
10
 
11
11
  begin
12
- require "rubocop/rake_task"
12
+ require 'rubocop/rake_task'
13
13
 
14
14
  Rake::Task[:default].enhance [:rubocop]
15
15
 
16
16
  RuboCop::RakeTask.new do |task|
17
- task.options << "--display-cop-names"
17
+ task.options << '--display-cop-names'
18
18
  end
19
19
  rescue LoadError
20
20
  end
@@ -3,8 +3,14 @@ require 'rom/sql'
3
3
  ::ROM::SQL.migration do
4
4
  change do
5
5
  postgres = database_type =~ /postgres/
6
- sqlite = database_type =~ /sqlite/
7
-
6
+
7
+ # set when copying migrations
8
+ # or when running tests
9
+ ENV['DATA_TYPE'] ||= 'text'
10
+ data_type = ENV['DATA_TYPE'].to_sym
11
+ data_types = postgres ? %i[text json jsonb] : %i[text]
12
+ raise ArgumentError, "DATA_TYPE must be: #{data_types.join(', ')}" unless data_types.include?(data_type)
13
+
8
14
  run 'CREATE EXTENSION IF NOT EXISTS pgcrypto;' if postgres
9
15
 
10
16
  create_table? :event_store_events_in_streams do
@@ -20,7 +26,7 @@ require 'rom/sql'
20
26
  end
21
27
 
22
28
  column :created_at, DateTime, null: false, index: 'index_event_store_events_in_streams_on_created_at'
23
-
29
+
24
30
  index %i[stream position], unique: true, name: 'index_event_store_events_in_streams_on_stream_and_position'
25
31
  index %i[stream event_id], unique: true, name: 'index_event_store_events_in_streams_on_stream_and_event_id'
26
32
  end
@@ -33,13 +39,16 @@ require 'rom/sql'
33
39
  end
34
40
 
35
41
  column :event_type, String, null: false
36
- column :metadata, String, text: true
37
- column :data, String, text: true, null: false
38
- column :created_at, DateTime, null: false, index: 'index_event_store_events_on_created_at'
39
42
 
40
- if sqlite # TODO: Is this relevant without ActiveRecord?
41
- index :id, unique: true
43
+ if data_type =~ /json/
44
+ column :metadata, data_type
45
+ column :data, data_type, null: false
46
+ else
47
+ column :metadata, String, text: true
48
+ column :data, String, text: true, null: false
42
49
  end
50
+
51
+ column :created_at, DateTime, null: false, index: 'index_event_store_events_on_created_at'
43
52
  end
44
53
  end
45
54
  end
@@ -2,7 +2,11 @@ require 'rom-changeset'
2
2
  require 'rom-mapper'
3
3
  require 'rom-repository'
4
4
  require 'ruby_event_store'
5
+ require 'ruby_event_store/rom/types'
5
6
  require 'ruby_event_store/rom/event_repository'
7
+ require 'ruby_event_store/rom/changesets/create_events'
8
+ require 'ruby_event_store/rom/changesets/update_events'
9
+ require 'ruby_event_store/rom/changesets/create_stream_entries'
6
10
  require 'ruby_event_store/rom/tuple_uniqueness_error'
7
11
  require 'ruby_event_store/rom/unit_of_work'
8
12
  require 'ruby_event_store/rom/version'
@@ -11,10 +15,10 @@ module RubyEventStore
11
15
  module ROM
12
16
  class Env
13
17
  attr_accessor :container
14
-
18
+
15
19
  def initialize(container)
16
20
  @container = container
17
-
21
+
18
22
  container.register(:unique_violation_error_handlers, Set.new)
19
23
  container.register(:not_found_error_handlers, Set.new)
20
24
  container.register(:logger, Logger.new(STDOUT).tap { |logger| logger.level = Logger::WARN })
@@ -26,25 +30,24 @@ module RubyEventStore
26
30
 
27
31
  def unit_of_work(&block)
28
32
  options = container[:unit_of_work_options].dup
29
- options.delete(:class){UnitOfWork}.new(rom: self).call(**options, &block)
33
+ options.delete(:class) { UnitOfWork }.new(rom: self).call(**options, &block)
30
34
  end
31
35
 
32
36
  def register_unit_of_work_options(options)
33
37
  container.register(:unit_of_work_options, options)
34
38
  end
35
-
39
+
36
40
  def register_error_handler(type, handler)
37
41
  container[:"#{type}_error_handlers"] << handler
38
42
  end
39
-
43
+
40
44
  def handle_error(type, *args, swallow: [])
41
45
  yield
42
- rescue => ex
46
+ rescue StandardError => ex
43
47
  begin
44
- container[:"#{type}_error_handlers"].each{ |h| h.call(ex, *args) }
48
+ container[:"#{type}_error_handlers"].each { |h| h.call(ex, *args) }
45
49
  raise ex
46
50
  rescue *swallow
47
- # swallow
48
51
  end
49
52
  end
50
53
  end
@@ -52,7 +55,7 @@ module RubyEventStore
52
55
  class << self
53
56
  # Set to a default instance
54
57
  attr_accessor :env
55
-
58
+
56
59
  def configure(adapter_name, database_uri = ENV['DATABASE_URL'], &block)
57
60
  if adapter_name.is_a?(::ROM::Configuration)
58
61
  # Call config block manually
@@ -61,20 +64,20 @@ module RubyEventStore
61
64
  Env.new ::ROM.container(adapter_name, database_uri, &block)
62
65
  end
63
66
  end
64
-
67
+
65
68
  def setup(*args, &block)
66
69
  configure(*args) do |config|
67
70
  setup_defaults(config)
68
- block.call(config) if block
71
+ yield(config) if block
69
72
  end.tap(&method(:configure_defaults))
70
73
  end
71
74
 
72
- private
73
-
75
+ private
76
+
74
77
  def setup_defaults(config)
75
78
  require_relative 'rom/repositories/stream_entries'
76
79
  require_relative 'rom/repositories/events'
77
-
80
+
78
81
  config.register_mapper(ROM::Mappers::EventToSerializedRecord)
79
82
  config.register_mapper(ROM::Mappers::StreamEntryToSerializedRecord)
80
83
 
@@ -84,10 +87,10 @@ module RubyEventStore
84
87
  end
85
88
 
86
89
  def configure_defaults(env)
87
- env.register_error_handler :not_found, -> (ex, event_id) {
90
+ env.register_error_handler :not_found, lambda { |ex, event_id|
88
91
  case ex
89
92
  when ::ROM::TupleCountMismatchError
90
- raise EventNotFound.new(event_id)
93
+ raise EventNotFound, event_id
91
94
  end
92
95
  }
93
96
 
@@ -0,0 +1,17 @@
1
+ module RubyEventStore
2
+ module ROM
3
+ module Memory
4
+ module Changesets
5
+ class CreateEvents < ROM::Changesets::CreateEvents
6
+ def commit
7
+ relation.by_pk(to_a.map { |e| e[:id] }).each do |tuple|
8
+ raise TupleUniquenessError.for_event_id(tuple[:id])
9
+ end
10
+
11
+ super
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module RubyEventStore
2
+ module ROM
3
+ module Memory
4
+ module Changesets
5
+ class CreateStreamEntries < ROM::Changesets::CreateStreamEntries
6
+ def commit
7
+ to_a.each do |tuple|
8
+ relation.send(:verify_uniquness!, tuple)
9
+ end
10
+
11
+ super
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module RubyEventStore
2
+ module ROM
3
+ module Memory
4
+ module Changesets
5
+ class UpdateEvents < ROM::Changesets::UpdateEvents
6
+ def commit
7
+ to_a.each do |params|
8
+ attributes = command.input[params].to_h.delete_if { |k, v| k == :created_at && v.nil? }
9
+ relation.by_pk(params.fetch(:id)).dataset.map { |tuple| tuple.update(attributes) }
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -8,18 +8,26 @@ module RubyEventStore
8
8
  attribute :event_type, ::ROM::Types::Strict::String
9
9
  attribute :metadata, ::ROM::Types::Strict::String.optional
10
10
  attribute :data, ::ROM::Types::Strict::String
11
- attribute :created_at, ::ROM::Types::Strict::Time.default { Time.now }
11
+ attribute :created_at, RubyEventStore::ROM::Types::DateTime
12
+ end
13
+
14
+ def create_changeset(tuples)
15
+ events.changeset(Changesets::CreateEvents, tuples)
16
+ end
17
+
18
+ def update_changeset(tuples)
19
+ events.changeset(Changesets::UpdateEvents, tuples)
12
20
  end
13
21
 
14
22
  def insert(tuple)
15
23
  verify_uniquness!(tuple)
16
24
  super
17
25
  end
18
-
26
+
19
27
  def for_stream_entries(_assoc, stream_entries)
20
28
  restrict(id: stream_entries.map { |e| e[:event_id] })
21
29
  end
22
-
30
+
23
31
  def by_pk(id)
24
32
  restrict(id: id)
25
33
  end
@@ -31,11 +39,12 @@ module RubyEventStore
31
39
  def pluck(name)
32
40
  map { |e| e[name] }
33
41
  end
34
-
35
- private
42
+
43
+ private
36
44
 
37
45
  def verify_uniquness!(tuple)
38
46
  return unless by_pk(tuple[:id]).exist?
47
+
39
48
  raise TupleUniquenessError.for_event_id(tuple[:id])
40
49
  end
41
50
  end
@@ -4,11 +4,11 @@ module RubyEventStore
4
4
  module Relations
5
5
  class StreamEntries < ::ROM::Relation[:memory]
6
6
  schema(:stream_entries) do
7
- attribute :id, ::ROM::Types::Strict::Int.meta(primary_key: true).default { RubyEventStore::ROM::Memory.fetch_next_id }
7
+ attribute(:id, ::ROM::Types::Strict::Int.meta(primary_key: true).default { RubyEventStore::ROM::Memory.fetch_next_id })
8
8
  attribute :stream, ::ROM::Types::Strict::String
9
9
  attribute :position, ::ROM::Types::Strict::Int.optional
10
10
  attribute :event_id, ::ROM::Types::Strict::String.meta(foreign_key: true, relation: :events)
11
- attribute :created_at, ::ROM::Types::Strict::Time.default { Time.now }
11
+ attribute :created_at, RubyEventStore::ROM::Types::DateTime
12
12
 
13
13
  associations do
14
14
  belongs_to :events, as: :event, foreign_key: :event_id, override: true, view: :for_stream_entries
@@ -23,6 +23,10 @@ module RubyEventStore
23
23
 
24
24
  SERIALIZED_GLOBAL_STREAM_NAME = 'all'.freeze
25
25
 
26
+ def create_changeset(tuples)
27
+ changeset(Changesets::CreateStreamEntries, tuples)
28
+ end
29
+
26
30
  def offset(num)
27
31
  num.zero? ? self : new(dataset.slice(num..-1) || [])
28
32
  end
@@ -61,7 +65,7 @@ module RubyEventStore
61
65
  end
62
66
 
63
67
  DIRECTION_MAP = {
64
- forward: [false, :>],
68
+ forward: [false, :>],
65
69
  backward: [true, :<]
66
70
  }.freeze
67
71
 
@@ -81,7 +85,7 @@ module RubyEventStore
81
85
  query
82
86
  end
83
87
 
84
- private
88
+ private
85
89
 
86
90
  # Verifies uniqueness of [stream, event_id] and [stream, position]
87
91
  def verify_uniquness!(tuple)
@@ -6,39 +6,24 @@ module RubyEventStore
6
6
  @mutex ||= Mutex.new
7
7
  end
8
8
 
9
- def commit!(gateway, changesets, **options)
9
+ def commit!(_gateway, changesets, **_options)
10
10
  self.class.mutex.synchronize do
11
11
  committed = []
12
-
12
+
13
13
  begin
14
- while changesets.size > 0
14
+ until changesets.empty?
15
15
  changeset = changesets.shift
16
16
  relation = env.container.relations[changeset.relation.name]
17
17
 
18
- case changeset
19
- when ROM::Repositories::Events::Create
20
- relation.by_pk(changeset.to_a.map{ |e| e[:id] }).each do |tuple|
21
- raise TupleUniquenessError.for_event_id(tuple[:id])
22
- end
23
- when ROM::Repositories::StreamEntries::Create
24
- changeset.to_a.each do |tuple|
25
- relation.send(:verify_uniquness!, tuple)
26
- end
27
- else
28
- raise ArgumentError, 'Unknown changeset'
29
- end
30
-
31
18
  committed << [changeset, relation]
32
19
 
33
20
  changeset.commit
34
21
  end
35
22
  rescue StandardError
36
- committed.reverse.each do |changeset, relation|
37
- relation
38
- .restrict(id: changeset.to_a.map { |e| e[:id] })
39
- .command(:delete, result: :many).call
23
+ committed.reverse_each do |c, r|
24
+ r.restrict(id: c.to_a.map { |e| e[:id] }).command(:delete, result: :many).call
40
25
  end
41
-
26
+
42
27
  raise
43
28
  end
44
29
  end