event_sourcery 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -2
  3. data/README.md +2 -2
  4. data/event_sourcery.gemspec +17 -10
  5. data/lib/event_sourcery/aggregate_root.rb +10 -3
  6. data/lib/event_sourcery/config.rb +6 -2
  7. data/lib/event_sourcery/errors.rb +3 -1
  8. data/lib/event_sourcery/event.rb +37 -19
  9. data/lib/event_sourcery/event_body_serializer.rb +5 -1
  10. data/lib/event_sourcery/event_processing/error_handlers/constant_retry.rb +5 -3
  11. data/lib/event_sourcery/event_processing/error_handlers/error_handler.rb +2 -0
  12. data/lib/event_sourcery/event_processing/error_handlers/exponential_backoff_retry.rb +8 -4
  13. data/lib/event_sourcery/event_processing/error_handlers/no_retry.rb +4 -2
  14. data/lib/event_sourcery/event_processing/esp_process.rb +3 -1
  15. data/lib/event_sourcery/event_processing/esp_runner.rb +7 -5
  16. data/lib/event_sourcery/event_processing/event_stream_processor.rb +8 -8
  17. data/lib/event_sourcery/event_processing/event_stream_processor_registry.rb +2 -0
  18. data/lib/event_sourcery/event_store/each_by_range.rb +6 -5
  19. data/lib/event_sourcery/event_store/event_builder.rb +2 -0
  20. data/lib/event_sourcery/event_store/event_sink.rb +2 -0
  21. data/lib/event_sourcery/event_store/event_source.rb +2 -0
  22. data/lib/event_sourcery/event_store/event_type_serializers/class_name.rb +2 -0
  23. data/lib/event_sourcery/event_store/event_type_serializers/legacy.rb +4 -2
  24. data/lib/event_sourcery/event_store/event_type_serializers/underscored.rb +17 -13
  25. data/lib/event_sourcery/event_store/poll_waiter.rb +7 -3
  26. data/lib/event_sourcery/event_store/signal_handling_subscription_master.rb +3 -1
  27. data/lib/event_sourcery/event_store/subscription.rb +7 -3
  28. data/lib/event_sourcery/memory/config.rb +2 -2
  29. data/lib/event_sourcery/memory/event_store.rb +23 -18
  30. data/lib/event_sourcery/memory/projector.rb +2 -1
  31. data/lib/event_sourcery/memory/tracker.rb +3 -1
  32. data/lib/event_sourcery/repository.rb +2 -0
  33. data/lib/event_sourcery/rspec/event_store_shared_examples.rb +28 -27
  34. data/lib/event_sourcery/version.rb +4 -2
  35. data/lib/event_sourcery.rb +2 -0
  36. metadata +34 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 101a542737fe302d06e518887e0663fc1855c331f17199cb00f8e43dbe5a16c5
4
- data.tar.gz: ffe47fc0617d3ad85978324d56e971226fab0269ed1d95c3bb8212567aa64415
3
+ metadata.gz: 415c43691713e1a778ed869039f81ab0af0b3d65b86a1c96805414e46bde2111
4
+ data.tar.gz: 623adde0b5dd6f1b850567c8485bf8204cbc5c38691ead0f9b3f5f947faa6fc0
5
5
  SHA512:
6
- metadata.gz: 3c0cfeb363bdfd8ed50d8ecbb73f974fc03aba6f802bd4f70a09f4465e1b27a7217d3c64e517e25af81fc32df531be2cdadc713c517825dc45b3e89f83cb4d16
7
- data.tar.gz: f375efcb3c9d3f09b31e0d01036747db045eb41e74b0feabb87dff069d0a90a52005f6d3829fe8ded28decf32078966c59214dfad2e168aa14759ff7625ef6de
6
+ metadata.gz: 6fdc34b508b5f3031eaabda5cce803d112e577e585f73716f0a29d3f7d6f5b3fb35f9fee4bd27e732ff5a05f7c0235313f3c08f6edc091a71ff0e253bb5f5f48
7
+ data.tar.gz: d3bd692067e4231ddbf4cbdc8a8de01dc4ce60963adc25166b052a3552e982563b76b4225606d1c18d7333e6c28dc97a9378faf9ae71a02da2f638c4012b7552
data/CHANGELOG.md CHANGED
@@ -7,11 +7,46 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ [Unreleased]: https://github.com/envato/event_sourcery/compare/v1.0.3...HEAD
11
+
12
+ ## [1.0.3] - 2025-12-29
13
+
14
+ ### Changed
15
+
16
+ - Resolve issues as identified by RuboCop ([#245]).
17
+
18
+ [1.0.3]: https://github.com/envato/event_sourcery/compare/v1.0.2...v1.0.3
19
+ [#245]: https://github.com/envato/event_sourcery/pull/245
20
+
21
+ ## [1.0.2] - 2025-12-28
22
+
23
+ ### Changed
24
+
25
+ - Minor fixups in gem metadata ([#240]).
26
+ - Resolve issues as identified by RuboCop ([#241], [#244]).
27
+ - Removed support for older Ruby versions: Ruby 2.6 or greater is now required ([#243]).
28
+
29
+ [1.0.2]: https://github.com/envato/event_sourcery/compare/v1.0.1...v1.0.2
30
+ [#240]: https://github.com/envato/event_sourcery/pull/240
31
+ [#241]: https://github.com/envato/event_sourcery/pull/241
32
+ [#243]: https://github.com/envato/event_sourcery/pull/243
33
+ [#244]: https://github.com/envato/event_sourcery/pull/244
34
+
35
+ ## [1.0.1] - 2025-12-27
36
+
37
+ ### Changed
38
+
39
+ - Support Ruby 4.0, make `logger` dependency explicit ([#239])
40
+
41
+ [1.0.1]: https://github.com/envato/event_sourcery/compare/v1.0.0...v1.0.1
42
+ [#239]: https://github.com/envato/event_sourcery/pull/239
43
+
10
44
  ## [1.0.0] - 2023-11-29
11
45
 
12
46
  ### Removed
13
47
  - Removed Event.persisted? as it was potentially misleading ([#235])
14
48
 
49
+ [1.0.0]: https://github.com/envato/event_sourcery/compare/v0.24.0...v1.0.0
15
50
  [#235]: https://github.com/envato/event_sourcery/pull/235
16
51
 
17
52
  ## [0.24.0] - 2021-11-18
@@ -261,8 +296,6 @@ moving all Postgres related code into a separate gem.
261
296
  - EventSourcery no longer depends on Virtus.
262
297
  - `Command` and `CommandHandler` have been removed.
263
298
 
264
- [Unreleased]: https://github.com/envato/event_sourcery/compare/v0.24.0...HEAD
265
- [1.0.0]: https://github.com/envato/event_sourcery/compare/v0.24.0...v1.0.0
266
299
  [0.24.0]: https://github.com/envato/event_sourcery/compare/v0.23.1...v0.24.0
267
300
  [0.23.1]: https://github.com/envato/event_sourcery/compare/v0.23.0...v0.23.1
268
301
  [0.23.0]: https://github.com/envato/event_sourcery/compare/v0.22.0...v0.23.0
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # EventSourcery
2
2
 
3
- [![Build Status](https://github.com/envato/event_sourcery/workflows/tests/badge.svg?branch=main)](https://github.com/envato/event_sourcery/actions?query=workflow%3Atests+branch%3Amain)
3
+ [![Build Status](https://github.com/envato/event_sourcery/actions/workflows/test.yml/badge.svg)](https://github.com/envato/event_sourcery/actions/workflows/test.yml)
4
4
 
5
5
  A framework for building event sourced, CQRS applications.
6
6
 
@@ -34,7 +34,7 @@ A framework for building event sourced, CQRS applications.
34
34
 
35
35
  ## Development Status
36
36
 
37
- [![Build Status](https://github.com/envato/event_sourcery/workflows/tests/badge.svg?branch=main)](https://github.com/envato/event_sourcery/actions?query=branch%3Amain)
37
+ [![Build Status](https://github.com/envato/event_sourcery/actions/workflows/test.yml/badge.svg)](https://github.com/envato/event_sourcery/actions/workflows/test.yml)
38
38
 
39
39
  Event Sourcery is in production use at [Envato](http://envato.com).
40
40
 
@@ -1,5 +1,6 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'event_sourcery/version'
5
6
 
@@ -12,24 +13,30 @@ Gem::Specification.new do |spec|
12
13
  spec.summary = 'Event Sourcing Library'
13
14
  spec.description = ''
14
15
  spec.homepage = 'https://github.com/envato/event_sourcery'
16
+ spec.license = 'MIT'
15
17
  spec.metadata = {
16
- 'bug_tracker_uri' => 'https://github.com/envato/event_sourcery/issues',
17
- 'changelog_uri' => 'https://github.com/envato/event_sourcery/blob/HEAD/CHANGELOG.md',
18
- 'source_code_uri' => 'https://github.com/envato/event_sourcery',
19
- }
18
+ 'allowed_push_host' => 'https://rubygems.org',
19
+ 'bug_tracker_uri' => "#{spec.homepage}/issues",
20
+ 'changelog_uri' => "#{spec.homepage}/blob/HEAD/CHANGELOG.md",
21
+ 'documentation_uri' => "https://www.rubydoc.info/gems/event_sourcery/#{spec.version}",
22
+ 'source_code_uri' => "#{spec.homepage}/tree/v#{spec.version}"
23
+ }
20
24
 
21
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(\.|Gemfile|Rakefile|bin/|script/|spec/)}) }
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(\.|Gemfile|Rakefile|bin/|script/|spec/)})
27
+ end
22
28
  spec.bindir = 'exe'
23
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
30
  spec.require_paths = ['lib']
25
31
 
26
- spec.required_ruby_version = '>= 2.2.0'
32
+ spec.required_ruby_version = '>= 2.6.0'
27
33
 
28
34
  spec.add_runtime_dependency 'logger'
29
35
 
36
+ spec.add_development_dependency 'benchmark-ips'
30
37
  spec.add_development_dependency 'bundler'
38
+ spec.add_development_dependency 'pry'
31
39
  spec.add_development_dependency 'rake', '~> 13'
32
40
  spec.add_development_dependency 'rspec'
33
- spec.add_development_dependency 'pry'
34
- spec.add_development_dependency 'benchmark-ips'
41
+ spec.add_development_dependency 'rubocop', '~> 1'
35
42
  end
@@ -1,9 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  #
3
5
  # EventSourcery::AggregateRoot provides a foundation for writing your own aggregate root classes.
4
6
  # You can use it by including it in your classes, as show in the example code.
5
7
  #
6
- # Excerpt from {https://github.com/envato/event_sourcery/blob/HEAD/docs/core-concepts.md EventSourcery Core Concepts} on Aggregates follows:
8
+ # Excerpt from {https://github.com/envato/event_sourcery/blob/HEAD/docs/core-concepts.md EventSourcery Core Concepts}
9
+ # on Aggregates follows:
10
+ #
7
11
  # === Aggregates and Command Handling
8
12
  #
9
13
  # An aggregate is a cluster of domain objects that can be treated as a single unit.
@@ -18,7 +22,8 @@ module EventSourcery
18
22
  # A typical EventSourcery application will have one or more aggregate roots with multiple commands.
19
23
  #
20
24
  # The following partial example is taken from the EventSourceryTodoApp.
21
- # Refer a more complete example {https://github.com/envato/event_sourcery_todo_app/blob/HEAD/app/aggregates/todo.rb here}.
25
+ # Refer a more complete example
26
+ # {https://github.com/envato/event_sourcery_todo_app/blob/HEAD/app/aggregates/todo.rb here}.
22
27
  #
23
28
  # @example
24
29
  # module EventSourceryTodoApp
@@ -85,7 +90,9 @@ module EventSourcery
85
90
  #
86
91
  # @param id [String] ID (a UUID represented as a string) of the aggregate instance to be loaded
87
92
  # @param events [Array] Events from which the aggregate's current state will be formed
88
- # @param on_unknown_event [Proc] Optional. The proc to be run if an unknown event type (for which no event handler is registered using {ClassMethods#apply}) is to be loaded.
93
+ # @param on_unknown_event [Proc] Optional. The proc to be run if an unknown
94
+ # event type (for which no event handler is registered using
95
+ # {ClassMethods#apply}) is to be loaded.
89
96
  def initialize(id, events, on_unknown_event: EventSourcery.config.on_unknown_event)
90
97
  @id = id.to_str
91
98
  @version = 0
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logger'
2
4
 
3
5
  module EventSourcery
@@ -60,7 +62,7 @@ module EventSourcery
60
62
  # Logger instance used by EventSourcery.
61
63
  # By default EventSourcery will log to STDOUT with a log level of Logger::INFO
62
64
  def logger
63
- @logger ||= ::Logger.new(STDOUT).tap do |logger|
65
+ @logger ||= ::Logger.new($stdout).tap do |logger|
64
66
  logger.level = Logger::INFO
65
67
  end
66
68
  end
@@ -76,7 +78,9 @@ module EventSourcery
76
78
  # ({EventStore::EventBuilder}). By default {EventBodySerializer} will be used.
77
79
  # Provide a custom serializer here to change how the event body is serialized.
78
80
  def event_body_serializer
79
- @event_body_serializer ||= EventBodySerializer.new
81
+ @event_body_serializer ||=
82
+ EventBodySerializer
83
+ .new
80
84
  .add(Hash, EventBodySerializer::HashSerializer)
81
85
  .add(Array, EventBodySerializer::ArraySerializer)
82
86
  .add(Time, &:iso8601)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  Error = Class.new(StandardError)
3
5
  UnableToLockProcessorError = Class.new(Error)
@@ -18,7 +20,7 @@ module EventSourcery
18
20
  parts << "#<#{processor.class} @@processor_name=#{processor.processor_name.inspect}>"
19
21
  parts << "#<#{event.class} @id=#{event.id.inspect}, @uuid=#{event.uuid.inspect}, @type=#{event.type.inspect}>"
20
22
  parts << "#<#{cause.class}: #{cause.message}>"
21
- parts.join("\n") + "\n"
23
+ "#{parts.join("\n")}\n"
22
24
  end
23
25
  end
24
26
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  # Represents an Event
3
5
  class Event
@@ -7,9 +9,9 @@ module EventSourcery
7
9
  #
8
10
  # Will return `nil` if called on an instance of {EventSourcery::Event}.
9
11
  def self.type
10
- unless self == Event
11
- EventSourcery.config.event_type_serializer.serialize(self)
12
- end
12
+ return if self == Event
13
+
14
+ EventSourcery.config.event_type_serializer.serialize(self)
13
15
  end
14
16
 
15
17
  # Use this method to add "upcasting" to your events.
@@ -61,19 +63,35 @@ module EventSourcery
61
63
  # @return [Time] Created at timestamp (in UTC) for the event.
62
64
 
63
65
  # @!attribute [r] correlation_id
64
- # @return [String] UUID attached to the event that allows reference to a particular transaction or event chain. This value is often supplied as part of a command issued by clients.
66
+ # @return [String] UUID attached to the event that allows reference to a
67
+ # particular transaction or event chain. This value is often supplied as
68
+ # part of a command issued by clients.
65
69
 
66
70
  # @!attribute [r] causation_id
67
71
  # @return [String] UUID of the event that caused this event.
68
72
 
69
73
  #
70
- # @param id [Integer] Optional. Unique identifier at the persistent layer. By default this will be set by the underlying persistence layer when persisting the event.
71
- # @param uuid [String] UUID as a string. Optional. Unique identifier for this event. A random UUID will be generated by default.
72
- # @param aggregate_id [String] UUID as a string. Aggregate instance UUID to which this event belongs to.
74
+ # @param id [Integer] Optional. Unique identifier at the persistent layer.
75
+ # By default this will be set by the underlying persistence layer when
76
+ # persisting the event.
77
+ #
78
+ # @param uuid [String] UUID as a string. Optional. Unique identifier for
79
+ # this event. A random UUID will be generated by default.
80
+ #
81
+ # @param aggregate_id [String] UUID as a string. Aggregate instance UUID to
82
+ # which this event belongs to.
83
+ #
73
84
  # @param type [Class] Optional. Event type. {Event.type} will be used by default.
74
- # @param version [String] Optional. Event's aggregate version. Used by some event stores to guard against concurrency errors.
85
+ #
86
+ # @param version [String] Optional. Event's aggregate version. Used by some
87
+ # event stores to guard against concurrency errors.
88
+ #
75
89
  # @param created_at [Time] Optional. Created at timestamp (in UTC) for the event.
76
- # @param correlation_id [String] Optional. UUID attached to the event that allows reference to a particular transaction or event chain. This value is often supplied as part of a command issued by clients.
90
+ #
91
+ # @param correlation_id [String] Optional. UUID attached to the event that
92
+ # allows reference to a particular transaction or event chain. This value
93
+ # is often supplied as part of a command issued by clients.
94
+ #
77
95
  # @param causation_id [String] Optional. UUID of the event that caused this event.
78
96
  def initialize(id: nil,
79
97
  uuid: SecureRandom.uuid,
@@ -85,8 +103,8 @@ module EventSourcery
85
103
  correlation_id: nil,
86
104
  causation_id: nil)
87
105
  @id = id
88
- @uuid = uuid && uuid.downcase
89
- @aggregate_id = aggregate_id && aggregate_id.to_str
106
+ @uuid = uuid&.downcase
107
+ @aggregate_id = aggregate_id&.to_str
90
108
  @type = self.class.type || type.to_s
91
109
  @body = body ? EventSourcery::EventBodySerializer.serialize(body) : {}
92
110
  @version = version ? Integer(version) : nil
@@ -143,15 +161,15 @@ module EventSourcery
143
161
  # @return Hash
144
162
  def to_h
145
163
  {
146
- id: id,
147
- uuid: uuid,
148
- aggregate_id: aggregate_id,
149
- type: type,
150
- body: body,
151
- version: version,
152
- created_at: created_at,
164
+ id: id,
165
+ uuid: uuid,
166
+ aggregate_id: aggregate_id,
167
+ type: type,
168
+ body: body,
169
+ version: version,
170
+ created_at: created_at,
153
171
  correlation_id: correlation_id,
154
- causation_id: causation_id,
172
+ causation_id: causation_id
155
173
  }
156
174
  end
157
175
  end
@@ -1,10 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  # EventBodySerializer is used for serializing event bodies when persisting events.
3
5
  class EventBodySerializer
4
6
  # Serialize the given event body, with the default or the provided, serializer
5
7
  #
6
8
  # @param event_body event body to be serialized
7
- # @param serializer Optional. Serializer to be used. By default {Config#event_body_serializer EventSourcery.config.event_body_serializer} will be used.
9
+ # @param serializer Optional. Serializer to be used. By default
10
+ # {Config#event_body_serializer EventSourcery.config.event_body_serializer}
11
+ # will be used.
8
12
  def self.serialize(event_body,
9
13
  serializer: EventSourcery.config.event_body_serializer)
10
14
  serializer.serialize(event_body)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventProcessing
3
5
  module ErrorHandlers
@@ -9,7 +11,7 @@ module EventSourcery
9
11
  #
10
12
  # @api private
11
13
  DEFAULT_RETRY_INTERVAL = 1
12
-
14
+
13
15
  def initialize(processor_name:)
14
16
  @processor_name = processor_name
15
17
  @retry_interval = DEFAULT_RETRY_INTERVAL
@@ -18,8 +20,8 @@ module EventSourcery
18
20
  # Will yield the block and attempt to retry after a defined retry interval {DEFAULT_RETRY_INTERVAL}.
19
21
  def with_error_handling
20
22
  yield
21
- rescue => error
22
- report_error(error)
23
+ rescue StandardError => e
24
+ report_error(e)
23
25
  sleep(@retry_interval)
24
26
 
25
27
  retry
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventProcessing
3
5
  module ErrorHandlers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventProcessing
3
5
  module ErrorHandlers
@@ -23,11 +25,13 @@ module EventSourcery
23
25
  # Will yield the block and attempt to retry in an exponential backoff.
24
26
  def with_error_handling
25
27
  yield
26
- rescue => error
27
- report_error(error)
28
- update_retry_interval(error)
28
+ rescue StandardError => e
29
+ report_error(e)
30
+ update_retry_interval(e)
29
31
  sleep(@retry_interval)
30
- EventSourcery.logger.info { "Retrying #{@processor_name} with error: #{error.message} at interval=#{@retry_interval}" }
32
+ EventSourcery.logger.info do
33
+ "Retrying #{@processor_name} with error: #{e.message} at interval=#{@retry_interval}"
34
+ end
31
35
  retry
32
36
  end
33
37
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventProcessing
3
5
  module ErrorHandlers
@@ -10,8 +12,8 @@ module EventSourcery
10
12
  # Will yield the block and exit the process if an error is raised.
11
13
  def with_error_handling
12
14
  yield
13
- rescue => error
14
- report_error(error)
15
+ rescue StandardError => e
16
+ report_error(e)
15
17
  Process.exit(false)
16
18
  end
17
19
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventProcessing
3
5
  class ESPProcess
4
- DEFAULT_AFTER_FORK = -> (event_processor) { }
6
+ DEFAULT_AFTER_FORK = ->(event_processor) {}
5
7
 
6
8
  def initialize(event_processor:,
7
9
  event_source:,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventProcessing
3
5
  # NOTE: databases should be disconnected before running this
@@ -30,9 +32,7 @@ module EventSourcery
30
32
  record_terminated_processes
31
33
  end
32
34
  terminate_remaining_processes
33
- until all_processes_terminated? || waited_long_enough?
34
- record_terminated_processes
35
- end
35
+ record_terminated_processes until all_processes_terminated? || waited_long_enough?
36
36
  kill_remaining_processes
37
37
  record_terminated_processes until all_processes_terminated?
38
38
  end
@@ -43,7 +43,7 @@ module EventSourcery
43
43
  process = ESPProcess.new(
44
44
  event_processor: event_processor,
45
45
  event_source: @event_source,
46
- after_fork: @after_fork,
46
+ after_fork: @after_fork
47
47
  )
48
48
  pid = Process.fork { process.start }
49
49
  @pids[pid] = event_processor
@@ -72,7 +72,7 @@ module EventSourcery
72
72
  end
73
73
 
74
74
  def listen_for_shutdown_signals
75
- %i(TERM INT).each do |signal|
75
+ %i[TERM INT].each do |signal|
76
76
  Signal.trap(signal) { shutdown }
77
77
  end
78
78
  end
@@ -81,6 +81,7 @@ module EventSourcery
81
81
  loop do
82
82
  yield
83
83
  break if shutdown_requested?
84
+
84
85
  sleep(1)
85
86
  end
86
87
  end
@@ -109,6 +110,7 @@ module EventSourcery
109
110
  logger.info("ESPRunner: Process #{event_processor&.processor_name || pid} " \
110
111
  "terminated with exit status: #{status.exitstatus.inspect}")
111
112
  next unless event_processor
113
+
112
114
  @exit_status &&= !!status.success?
113
115
  @after_subprocess_termination&.call(processor: event_processor, runner: self, exit_status: status.exitstatus)
114
116
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventProcessing
3
5
  module EventStreamProcessor
@@ -31,13 +33,12 @@ module EventSourcery
31
33
  instance_exec(event, &handler)
32
34
  end
33
35
  @_event = nil
34
- rescue
36
+ rescue StandardError
35
37
  raise EventProcessingError.new(event: event, processor: self)
36
38
  end
37
39
  end
38
40
 
39
41
  module ClassMethods
40
-
41
42
  # @attr_reader processes_event_types [Array] Process Event Types
42
43
  # @attr_reader event_handlers [Hash] Hash of handler blocks keyed by event
43
44
  # @attr_reader all_event_handler [Proc] An event handler
@@ -49,8 +50,7 @@ module EventSourcery
49
50
  #
50
51
  # @return [True, False]
51
52
  def processes?(event_type)
52
- processes_event_types &&
53
- processes_event_types.include?(event_type.to_s)
53
+ processes_event_types&.include?(event_type.to_s)
54
54
  end
55
55
 
56
56
  # Set the name of the processor.
@@ -75,9 +75,9 @@ module EventSourcery
75
75
  if event_classes.empty?
76
76
  if @all_event_handler
77
77
  raise MultipleCatchAllHandlersDefined, 'Attemping to define multiple catch all event handlers.'
78
- else
79
- @all_event_handler = block
80
78
  end
79
+
80
+ @all_event_handler = block
81
81
  else
82
82
  @processes_event_types ||= []
83
83
  event_classes.each do |event_class|
@@ -127,8 +127,8 @@ module EventSourcery
127
127
  def subscribe_to(event_source, subscription_master: EventStore::SignalHandlingSubscriptionMaster.new)
128
128
  setup
129
129
  event_source.subscribe(from_id: last_processed_event_id + 1,
130
- event_types: processes_event_types,
131
- subscription_master: subscription_master) do |events|
130
+ event_types: processes_event_types,
131
+ subscription_master: subscription_master) do |events|
132
132
  process_events(events, subscription_master)
133
133
  end
134
134
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventProcessing
3
5
  class EventStreamProcessorRegistry
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventStore
3
5
  module EachByRange
@@ -5,7 +7,7 @@ module EventSourcery
5
7
  caught_up = false
6
8
  no_events_left = false
7
9
  event_id = from_event_id
8
- begin
10
+ loop do
9
11
  events = get_next_from(event_id, event_types: event_types)
10
12
  no_events_left = true if events.empty?
11
13
  events.each do |event|
@@ -15,10 +17,9 @@ module EventSourcery
15
17
  break
16
18
  end
17
19
  end
18
- unless no_events_left
19
- event_id = events.last.id + 1
20
- end
21
- end while !caught_up && !no_events_left
20
+ event_id = events.last.id + 1 unless no_events_left
21
+ break if caught_up || no_events_left
22
+ end
22
23
  end
23
24
  end
24
25
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventStore
3
5
  class EventBuilder
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
 
3
5
  module EventSourcery
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventStore
3
5
  class EventSource
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventStore
3
5
  module EventTypeSerializers
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventStore
3
5
  module EventTypeSerializers
4
6
  # To support legacy implementations. Type is provided when initializing
5
7
  # the event, not derived from the class constant
6
8
  class Legacy
7
- def serialize(event_class)
9
+ def serialize(_event_class)
8
10
  nil
9
11
  end
10
12
 
11
- def deserialize(event_type)
13
+ def deserialize(_event_type)
12
14
  Event
13
15
  end
14
16
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventStore
3
5
  module EventTypeSerializers
@@ -13,32 +15,34 @@ module EventSourcery
13
15
  def underscore(camel_cased_word)
14
16
  word = camel_cased_word.to_s.dup
15
17
  word.gsub!(/::/, '/')
16
- word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
17
- word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
18
- word.tr!("-", "_")
18
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
19
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
20
+ word.tr!('-', '_')
19
21
  word.downcase!
20
22
  word
21
23
  end
22
24
 
23
25
  def camelize(term, uppercase_first_letter = true)
24
26
  string = term.to_s
25
- if uppercase_first_letter
26
- string = string.sub(/^[a-z\d]*/) { capitalize($&) }
27
- else
28
- string = string.sub(/^(?:(?=\b|[A-Z_])|\w)/) { $&.downcase }
29
- end
30
- string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{capitalize($2)}" }.gsub('/', '::')
27
+ string =
28
+ if uppercase_first_letter
29
+ string.sub(/^[a-z\d]*/) { capitalize(::Regexp.last_match(0)) }
30
+ else
31
+ string.sub(/^(?:(?=\b|[A-Z_])|\w)/) { ::Regexp.last_match(0).downcase }
32
+ end
33
+ string.gsub(%r{(?:_|(/))([a-z\d]*)}i) do
34
+ "#{::Regexp.last_match(1)}#{capitalize(::Regexp.last_match(2))}"
35
+ end.gsub('/', '::')
31
36
  end
32
37
 
33
38
  private
34
39
 
35
40
  def capitalize(lower_case_and_underscored_word)
36
41
  result = lower_case_and_underscored_word.to_s.dup
37
- result.gsub!(/_id$/, "")
42
+ result.gsub!(/_id$/, '')
38
43
  result.gsub!(/_/, ' ')
39
- result.gsub(/([a-z\d]*)/i) { |match|
40
- "#{match.downcase}"
41
- }.gsub(/^\w/) { $&.upcase }
44
+ result.gsub!(/([a-z\d]*)/i, &:downcase)
45
+ result.gsub(/^\w/) { ::Regexp.last_match(0).upcase }
42
46
  end
43
47
  end
44
48
 
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventStore
3
-
4
- # This class provides a basic poll waiter implementation that calls the provided block and sleeps for the specified interval, to be used by a {Subscription}.
5
+ # This class provides a basic poll waiter implementation that calls the
6
+ # provided block and sleeps for the specified interval, to be used by a
7
+ # {Subscription}.
5
8
  class PollWaiter
6
9
  #
7
10
  # @param interval [Float] Optional. Will default to `0.5`
@@ -9,7 +12,8 @@ module EventSourcery
9
12
  @interval = interval
10
13
  end
11
14
 
12
- # Start polling. Call the provided block and sleep. Repeat until `:stop` is thrown (usually via a subscription master).
15
+ # Start polling. Call the provided block and sleep. Repeat until `:stop`
16
+ # is thrown (usually via a subscription master).
13
17
  #
14
18
  # @param block [Proc] code block to be called when polling
15
19
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventStore
3
5
  # Manages shutdown signals and facilitate graceful shutdowns of subscriptions.
@@ -20,7 +22,7 @@ module EventSourcery
20
22
  private
21
23
 
22
24
  def setup_graceful_shutdown
23
- %i(TERM INT).each do |signal|
25
+ %i[TERM INT].each do |signal|
24
26
  Signal.trap(signal) do
25
27
  @shutdown_requested = true
26
28
  wakeup_main_thread
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module EventStore
3
-
4
5
  # This allows Event Stream Processors (ESPs) to subscribe to an event store, and be notified when new events are
5
6
  # added.
6
7
  class Subscription
@@ -10,14 +11,16 @@ module EventSourcery
10
11
  # @param from_event_id [Integer] Start reading events from this event ID
11
12
  # @param event_types [Array] Optional. If specified, only subscribe to given event types.
12
13
  # @param on_new_events [Proc] Code block to be executed when new events are received
13
- # @param subscription_master A subscription master instance (such as {EventStore::SignalHandlingSubscriptionMaster}) which orchestrates a graceful shutdown of the subscription, if one is requested.
14
+ # @param subscription_master A subscription master instance (such as
15
+ # {EventStore::SignalHandlingSubscriptionMaster}) which orchestrates a
16
+ # graceful shutdown of the subscription, if one is requested.
14
17
  # @param events_table_name [Symbol] Optional. Defaults to `:events`
15
18
  def initialize(event_store:,
16
19
  poll_waiter:,
17
20
  from_event_id:,
18
- event_types: nil,
19
21
  on_new_events:,
20
22
  subscription_master:,
23
+ event_types: nil,
21
24
  events_table_name: :events,
22
25
  batch_size: EventSourcery.config.subscription_batch_size)
23
26
  @event_store = event_store
@@ -51,6 +54,7 @@ module EventSourcery
51
54
  @subscription_master.shutdown_if_requested
52
55
  events = @event_store.get_next_from(@current_event_id + 1, event_types: @event_types, limit: batch_size)
53
56
  break if events.empty?
57
+
54
58
  EventSourcery.logger.debug { "New events in subscription: #{events.inspect}" }
55
59
  @on_new_events.call(events)
56
60
  @current_event_id = events.last.id
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module Memory
3
5
  class Config
@@ -19,7 +21,6 @@ module EventSourcery
19
21
  def event_sink
20
22
  @event_sink ||= ::EventSourcery::EventStore::EventSink.new(event_store)
21
23
  end
22
-
23
24
  end
24
25
 
25
26
  def self.configure
@@ -29,6 +30,5 @@ module EventSourcery
29
30
  def self.config
30
31
  @config ||= Config.new
31
32
  end
32
-
33
33
  end
34
34
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module Memory
3
5
  # In-memory event store.
@@ -18,16 +20,17 @@ module EventSourcery
18
20
  # Store given events to the in-memory store
19
21
  #
20
22
  # @param event_or_events Event(s) to be stored
21
- # @param expected_version [Optional] Expected version for the aggregate. This is the version the caller of this method expect the aggregate to be in. If it's different from the expected version a {EventSourcery::ConcurrencyError} will be raised. Defaults to nil.
23
+ # @param expected_version [Optional] Expected version for the aggregate.
24
+ # This is the version the caller of this method expect the aggregate to
25
+ # be in. If it's different from the expected version a
26
+ # {EventSourcery::ConcurrencyError} will be raised. Defaults to nil.
22
27
  # @raise EventSourcery::ConcurrencyError
23
28
  # @return Boolean
24
29
  def sink(event_or_events, expected_version: nil)
25
30
  events = Array(event_or_events)
26
31
  ensure_one_aggregate(events)
27
32
 
28
- if expected_version && version_for(events.first.aggregate_id) != expected_version
29
- raise ConcurrencyError
30
- end
33
+ raise ConcurrencyError if expected_version && version_for(events.first.aggregate_id) != expected_version
31
34
 
32
35
  events.each do |event|
33
36
  @events << @event_builder.build(
@@ -39,7 +42,7 @@ module EventSourcery
39
42
  created_at: event.created_at || Time.now.utc,
40
43
  uuid: event.uuid,
41
44
  correlation_id: event.correlation_id,
42
- causation_id: event.causation_id,
45
+ causation_id: event.causation_id
43
46
  )
44
47
  end
45
48
 
@@ -55,11 +58,12 @@ module EventSourcery
55
58
  # @param limit [Integer] Optional. Number of events to retrieve (starting from the given event ID).
56
59
  # @return Array
57
60
  def get_next_from(id, event_types: nil, limit: 1000)
58
- events = if event_types.nil?
59
- @events
60
- else
61
- @events.select { |e| event_types.include?(e.type) }
62
- end
61
+ events =
62
+ if event_types.nil?
63
+ @events
64
+ else
65
+ @events.select { |e| event_types.include?(e.type) }
66
+ end
63
67
 
64
68
  events.select { |event| event.id >= id }.first(limit)
65
69
  end
@@ -69,11 +73,12 @@ module EventSourcery
69
73
  # @param event_types [Array] Optional. If supplied, only retrieve events of given type(s).
70
74
  # @return Integer
71
75
  def latest_event_id(event_types: nil)
72
- events = if event_types.nil?
73
- @events
74
- else
75
- @events.select { |e| event_types.include?(e.type) }
76
- end
76
+ events =
77
+ if event_types.nil?
78
+ @events
79
+ else
80
+ @events.select { |e| event_types.include?(e.type) }
81
+ end
77
82
 
78
83
  events.empty? ? 0 : events.last.id
79
84
  end
@@ -108,9 +113,9 @@ module EventSourcery
108
113
  # @param events [Array] Collection of events
109
114
  # @raise AtomicWriteToMultipleAggregatesNotSupported
110
115
  def ensure_one_aggregate(events)
111
- unless events.map(&:aggregate_id).uniq.one?
112
- raise AtomicWriteToMultipleAggregatesNotSupported
113
- end
116
+ return if events.map(&:aggregate_id).uniq.one?
117
+
118
+ raise AtomicWriteToMultipleAggregatesNotSupported
114
119
  end
115
120
 
116
121
  # Adds a listener or listeners to the memory store.
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module Memory
3
5
  module Projector
4
-
5
6
  def self.included(base)
6
7
  base.include(EventSourcery::EventProcessing::EventStreamProcessor)
7
8
  base.include(InstanceMethods)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  module Memory
3
5
  # Being able to know where you're at when reading an event stream
@@ -26,7 +28,7 @@ module EventSourcery
26
28
  @state[processor_name.to_s] = event_id
27
29
  end
28
30
 
29
- alias :reset_last_processed_event_id :setup
31
+ alias reset_last_processed_event_id setup
30
32
 
31
33
  # Find the last processed event id for a given processor name.
32
34
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
4
  # This class provides a set of methods to help load and save aggregate instances.
3
5
  #
@@ -1,11 +1,13 @@
1
- RSpec.shared_examples 'an event store' do
2
- TestEvent2 = Class.new(EventSourcery::Event)
3
- UserSignedUp = Class.new(EventSourcery::Event)
4
- ItemRejected = Class.new(EventSourcery::Event)
5
- Type1 = Class.new(EventSourcery::Event)
6
- Type2 = Class.new(EventSourcery::Event)
7
- BillingDetailsProvided = Class.new(EventSourcery::Event)
1
+ # frozen_string_literal: true
2
+
3
+ TestEvent2 = Class.new(EventSourcery::Event)
4
+ UserSignedUp = Class.new(EventSourcery::Event)
5
+ ItemRejected = Class.new(EventSourcery::Event)
6
+ Type1 = Class.new(EventSourcery::Event)
7
+ Type2 = Class.new(EventSourcery::Event)
8
+ BillingDetailsProvided = Class.new(EventSourcery::Event)
8
9
 
10
+ RSpec.shared_examples 'an event store' do
9
11
  let(:aggregate_id) { SecureRandom.uuid }
10
12
 
11
13
  describe '#sink' do
@@ -51,22 +53,22 @@ RSpec.shared_examples 'an event store' do
51
53
  end
52
54
 
53
55
  it 'writes multiple events' do
54
- event_store.sink([ItemAdded.new(aggregate_id: aggregate_id, body: {e: 1}),
55
- ItemAdded.new(aggregate_id: aggregate_id, body: {e: 2}),
56
- ItemAdded.new(aggregate_id: aggregate_id, body: {e: 3})])
56
+ event_store.sink([ItemAdded.new(aggregate_id: aggregate_id, body: { e: 1 }),
57
+ ItemAdded.new(aggregate_id: aggregate_id, body: { e: 2 }),
58
+ ItemAdded.new(aggregate_id: aggregate_id, body: { e: 3 })])
57
59
  events = event_store.get_next_from(1)
58
60
  expect(events.count).to eq 3
59
61
  expect(events.map(&:id)).to eq [1, 2, 3]
60
- expect(events.map(&:body)).to eq [{'e' => 1}, {'e' => 2}, {'e' => 3}]
62
+ expect(events.map(&:body)).to eq [{ 'e' => 1 }, { 'e' => 2 }, { 'e' => 3 }]
61
63
  expect(events.map(&:version)).to eq [1, 2, 3]
62
64
  end
63
65
 
64
66
  it 'sets the correct aggregates version' do
65
- event_store.sink([ItemAdded.new(aggregate_id: aggregate_id, body: {e: 1}),
66
- ItemAdded.new(aggregate_id: aggregate_id, body: {e: 2})])
67
+ event_store.sink([ItemAdded.new(aggregate_id: aggregate_id, body: { e: 1 }),
68
+ ItemAdded.new(aggregate_id: aggregate_id, body: { e: 2 })])
67
69
  # this will throw a unique constrain error if the aggregate version was not set correctly ^
68
- event_store.sink([ItemAdded.new(aggregate_id: aggregate_id, body: {e: 1}),
69
- ItemAdded.new(aggregate_id: aggregate_id, body: {e: 2})])
70
+ event_store.sink([ItemAdded.new(aggregate_id: aggregate_id, body: { e: 1 }),
71
+ ItemAdded.new(aggregate_id: aggregate_id, body: { e: 2 })])
70
72
  events = event_store.get_next_from(1)
71
73
  expect(events.count).to eq 4
72
74
  expect(events.map(&:id)).to eq [1, 2, 3, 4]
@@ -104,16 +106,17 @@ RSpec.shared_examples 'an event store' do
104
106
 
105
107
  it 'correctly inserts created at times when inserting multiple events atomically' do
106
108
  time = Time.parse('2016-10-14T00:00:00.646191Z')
107
- event_store.sink([ItemAdded.new(aggregate_id: aggregate_id, created_at: nil), ItemAdded.new(aggregate_id: aggregate_id, created_at: time)])
109
+ event_store.sink([ItemAdded.new(aggregate_id: aggregate_id, created_at: nil),
110
+ ItemAdded.new(aggregate_id: aggregate_id, created_at: time)])
108
111
  created_ats = event_store.get_next_from(0).map(&:created_at)
109
112
  expect(created_ats.map(&:class)).to eq [Time, Time]
110
113
  expect(created_ats.last).to eq time
111
114
  end
112
115
 
113
116
  it 'raises an error if the events given are for more than one aggregate' do
114
- expect {
117
+ expect do
115
118
  event_store.sink([ItemAdded.new(aggregate_id: aggregate_id), ItemAdded.new(aggregate_id: SecureRandom.uuid)])
116
- }.to raise_error(EventSourcery::AtomicWriteToMultipleAggregatesNotSupported)
119
+ end.to raise_error(EventSourcery::AtomicWriteToMultipleAggregatesNotSupported)
117
120
  end
118
121
  end
119
122
 
@@ -168,7 +171,7 @@ RSpec.shared_examples 'an event store' do
168
171
 
169
172
  expect(event_store.latest_event_id(event_types: ['type1'])).to eq 2
170
173
  expect(event_store.latest_event_id(event_types: ['type2'])).to eq 3
171
- expect(event_store.latest_event_id(event_types: ['type1', 'type2'])).to eq 3
174
+ expect(event_store.latest_event_id(event_types: %w[type1 type2])).to eq 3
172
175
  end
173
176
  end
174
177
  end
@@ -207,7 +210,7 @@ RSpec.shared_examples 'an event store' do
207
210
 
208
211
  describe '#each_by_range' do
209
212
  before do
210
- (1..21).each do |i|
213
+ 21.times do
211
214
  event_store.sink(ItemAdded.new(aggregate_id: aggregate_id, body: {}))
212
215
  end
213
216
  end
@@ -255,7 +258,7 @@ RSpec.shared_examples 'an event store' do
255
258
  def save_event(expected_version: nil)
256
259
  event_store.sink(
257
260
  BillingDetailsProvided.new(aggregate_id: aggregate_id, body: { my_event: 'data' }),
258
- expected_version: expected_version,
261
+ expected_version: expected_version
259
262
  )
260
263
  end
261
264
 
@@ -278,9 +281,8 @@ RSpec.shared_examples 'an event store' do
278
281
 
279
282
  context 'and the expected version is incorrect - 1' do
280
283
  it 'raises a ConcurrencyError' do
281
- expect {
282
- save_event(expected_version: 1)
283
- }.to raise_error(EventSourcery::ConcurrencyError)
284
+ expect { save_event(expected_version: 1) }
285
+ .to raise_error(EventSourcery::ConcurrencyError)
284
286
  end
285
287
  end
286
288
 
@@ -299,9 +301,8 @@ RSpec.shared_examples 'an event store' do
299
301
 
300
302
  context 'with an incorrect expected version - 0' do
301
303
  it 'raises a ConcurrencyError' do
302
- expect {
303
- save_event(expected_version: 0)
304
- }.to raise_error(EventSourcery::ConcurrencyError)
304
+ expect { save_event(expected_version: 0) }
305
+ .to raise_error(EventSourcery::ConcurrencyError)
305
306
  end
306
307
  end
307
308
 
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EventSourcery
2
- # Defines the version
3
- VERSION = '1.0.1'.freeze
4
+ # The version of the EventSourcery gem
5
+ VERSION = '1.0.3'
4
6
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'securerandom'
3
5
  require 'time'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: event_sourcery
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Envato
@@ -24,7 +24,7 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0'
26
26
  - !ruby/object:Gem::Dependency
27
- name: bundler
27
+ name: benchmark-ips
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
@@ -38,21 +38,21 @@ dependencies:
38
38
  - !ruby/object:Gem::Version
39
39
  version: '0'
40
40
  - !ruby/object:Gem::Dependency
41
- name: rake
41
+ name: bundler
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "~>"
44
+ - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: '13'
46
+ version: '0'
47
47
  type: :development
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - "~>"
51
+ - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: '13'
53
+ version: '0'
54
54
  - !ruby/object:Gem::Dependency
55
- name: rspec
55
+ name: pry
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
@@ -66,21 +66,21 @@ dependencies:
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0'
68
68
  - !ruby/object:Gem::Dependency
69
- name: pry
69
+ name: rake
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - ">="
72
+ - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: '0'
74
+ version: '13'
75
75
  type: :development
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - ">="
79
+ - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '0'
81
+ version: '13'
82
82
  - !ruby/object:Gem::Dependency
83
- name: benchmark-ips
83
+ name: rspec
84
84
  requirement: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - ">="
@@ -93,6 +93,20 @@ dependencies:
93
93
  - - ">="
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rubocop
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1'
96
110
  description: ''
97
111
  email:
98
112
  - rubygems@envato.com
@@ -137,11 +151,14 @@ files:
137
151
  - lib/event_sourcery/rspec/event_store_shared_examples.rb
138
152
  - lib/event_sourcery/version.rb
139
153
  homepage: https://github.com/envato/event_sourcery
140
- licenses: []
154
+ licenses:
155
+ - MIT
141
156
  metadata:
157
+ allowed_push_host: https://rubygems.org
142
158
  bug_tracker_uri: https://github.com/envato/event_sourcery/issues
143
159
  changelog_uri: https://github.com/envato/event_sourcery/blob/HEAD/CHANGELOG.md
144
- source_code_uri: https://github.com/envato/event_sourcery
160
+ documentation_uri: https://www.rubydoc.info/gems/event_sourcery/1.0.3
161
+ source_code_uri: https://github.com/envato/event_sourcery/tree/v1.0.3
145
162
  rdoc_options: []
146
163
  require_paths:
147
164
  - lib
@@ -149,7 +166,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
149
166
  requirements:
150
167
  - - ">="
151
168
  - !ruby/object:Gem::Version
152
- version: 2.2.0
169
+ version: 2.6.0
153
170
  required_rubygems_version: !ruby/object:Gem::Requirement
154
171
  requirements:
155
172
  - - ">="