ruby_event_store 1.2.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/lib/ruby_event_store.rb +3 -7
- data/lib/ruby_event_store/broker.rb +3 -3
- data/lib/ruby_event_store/client.rb +47 -23
- data/lib/ruby_event_store/composed_dispatcher.rb +2 -2
- data/lib/ruby_event_store/constants.rb +1 -0
- data/lib/ruby_event_store/errors.rb +0 -1
- data/lib/ruby_event_store/event.rb +8 -1
- data/lib/ruby_event_store/immediate_async_dispatcher.rb +2 -2
- data/lib/ruby_event_store/in_memory_repository.rb +98 -59
- data/lib/ruby_event_store/instrumented_dispatcher.rb +2 -2
- data/lib/ruby_event_store/instrumented_repository.rb +3 -3
- data/lib/ruby_event_store/mappers/default.rb +3 -8
- data/lib/ruby_event_store/mappers/encryption_mapper.rb +3 -4
- data/lib/ruby_event_store/mappers/instrumented_mapper.rb +4 -4
- data/lib/ruby_event_store/mappers/json_mapper.rb +7 -7
- data/lib/ruby_event_store/mappers/pipeline.rb +2 -5
- data/lib/ruby_event_store/mappers/pipeline_mapper.rb +2 -2
- data/lib/ruby_event_store/mappers/transformation/domain_event.rb +16 -8
- data/lib/ruby_event_store/mappers/transformation/encryption.rb +20 -12
- data/lib/ruby_event_store/mappers/transformation/event_class_remapper.rb +11 -4
- data/lib/ruby_event_store/mappers/transformation/stringify_metadata_keys.rb +12 -7
- data/lib/ruby_event_store/mappers/transformation/symbolize_metadata_keys.rb +12 -7
- data/lib/ruby_event_store/mappers/transformation/upcast.rb +37 -0
- data/lib/ruby_event_store/null.rb +13 -0
- data/lib/ruby_event_store/projection.rb +2 -1
- data/lib/ruby_event_store/record.rb +68 -0
- data/lib/ruby_event_store/serialized_record.rb +23 -4
- data/lib/ruby_event_store/spec/broker_lint.rb +9 -9
- data/lib/ruby_event_store/spec/event_repository_lint.rb +267 -105
- data/lib/ruby_event_store/spec/mapper_lint.rb +6 -6
- data/lib/ruby_event_store/spec/subscriptions_lint.rb +25 -0
- data/lib/ruby_event_store/specification.rb +100 -7
- data/lib/ruby_event_store/specification_reader.rb +2 -2
- data/lib/ruby_event_store/specification_result.rb +86 -2
- data/lib/ruby_event_store/subscriptions.rb +23 -9
- data/lib/ruby_event_store/transform_keys.rb +5 -5
- data/lib/ruby_event_store/version.rb +1 -1
- metadata +15 -21
- data/CHANGELOG.md +0 -93
- data/Gemfile +0 -11
- data/Makefile +0 -22
- data/lib/ruby_event_store/mappers/protobuf.rb +0 -24
- data/lib/ruby_event_store/mappers/transformation/item.rb +0 -56
- data/lib/ruby_event_store/mappers/transformation/proto_event.rb +0 -17
- data/lib/ruby_event_store/mappers/transformation/protobuf_encoder.rb +0 -30
- data/lib/ruby_event_store/mappers/transformation/protobuf_nested_struct_metadata.rb +0 -30
- data/lib/ruby_event_store/mappers/transformation/serialization.rb +0 -34
- data/lib/ruby_event_store/mappers/transformation/serialized_record.rb +0 -27
- data/ruby_event_store.gemspec +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88203a9b943002241df25fa83c6f067e7944810e66d713eeb11e8cebf13271e2
|
4
|
+
data.tar.gz: 1b032e898517d787a2e6d0cb6b15775792591abc094e68d2483590f916e69c9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 780c9e0f6064311d45be29c0553c47e65e679a3967b91e6caca48a55ef9c34a06070e421b1413c1a35634c6e45c1452204ac29fae2aa706fe7a0e46d1dd99f40
|
7
|
+
data.tar.gz: 66b7a11ce2d3b58a5f9c2690a7f7f998fc9130c302343923cdd5a57a63d6a398ea258cced2d1b3161e07d9fb081d04bd7c4f305d6576cae59bd6e50f50ba6a92
|
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
1
|
# RubyEventStore
|
2
2
|
|
3
|
-
|
3
|
+
Ruby implementation of an event store. Ships with in-memory event repository, generic instrumentation and dispatches events synchronously.
|
4
|
+
|
5
|
+
Find out more at [https://railseventstore.org](https://railseventstore.org/)
|
data/lib/ruby_event_store.rb
CHANGED
@@ -15,19 +15,16 @@ require 'ruby_event_store/specification_reader'
|
|
15
15
|
require 'ruby_event_store/event'
|
16
16
|
require 'ruby_event_store/stream'
|
17
17
|
require 'ruby_event_store/expected_version'
|
18
|
+
require 'ruby_event_store/record'
|
18
19
|
require 'ruby_event_store/serialized_record'
|
20
|
+
require 'ruby_event_store/null'
|
19
21
|
require 'ruby_event_store/transform_keys'
|
20
22
|
require 'ruby_event_store/mappers/encryption_key'
|
21
23
|
require 'ruby_event_store/mappers/in_memory_encryption_key_repository'
|
22
24
|
require 'ruby_event_store/mappers/transformation/domain_event'
|
23
25
|
require 'ruby_event_store/mappers/transformation/encryption'
|
24
26
|
require 'ruby_event_store/mappers/transformation/event_class_remapper'
|
25
|
-
require 'ruby_event_store/mappers/transformation/
|
26
|
-
require 'ruby_event_store/mappers/transformation/proto_event'
|
27
|
-
require 'ruby_event_store/mappers/transformation/protobuf_encoder'
|
28
|
-
require 'ruby_event_store/mappers/transformation/protobuf_nested_struct_metadata'
|
29
|
-
require 'ruby_event_store/mappers/transformation/serialization'
|
30
|
-
require 'ruby_event_store/mappers/transformation/serialized_record'
|
27
|
+
require 'ruby_event_store/mappers/transformation/upcast'
|
31
28
|
require 'ruby_event_store/mappers/transformation/stringify_metadata_keys'
|
32
29
|
require 'ruby_event_store/mappers/transformation/symbolize_metadata_keys'
|
33
30
|
require 'ruby_event_store/mappers/pipeline'
|
@@ -38,7 +35,6 @@ require 'ruby_event_store/mappers/encryption_mapper'
|
|
38
35
|
require 'ruby_event_store/mappers/instrumented_mapper'
|
39
36
|
require 'ruby_event_store/mappers/json_mapper'
|
40
37
|
require 'ruby_event_store/mappers/null_mapper'
|
41
|
-
require 'ruby_event_store/mappers/protobuf'
|
42
38
|
require 'ruby_event_store/batch_enumerator'
|
43
39
|
require 'ruby_event_store/correlated_commands'
|
44
40
|
require 'ruby_event_store/link_by_metadata'
|
@@ -7,10 +7,10 @@ module RubyEventStore
|
|
7
7
|
@dispatcher = dispatcher
|
8
8
|
end
|
9
9
|
|
10
|
-
def call(event,
|
10
|
+
def call(event, record)
|
11
11
|
subscribers = subscriptions.all_for(event.event_type)
|
12
12
|
subscribers.each do |subscriber|
|
13
|
-
dispatcher.call(subscriber, event,
|
13
|
+
dispatcher.call(subscriber, event, record)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -35,7 +35,7 @@ module RubyEventStore
|
|
35
35
|
end
|
36
36
|
|
37
37
|
private
|
38
|
-
attr_reader :
|
38
|
+
attr_reader :dispatcher, :subscriptions
|
39
39
|
|
40
40
|
def verify_subscription(subscriber)
|
41
41
|
raise SubscriberNotExist, "subscriber must be first argument or block" unless subscriber
|
@@ -10,8 +10,11 @@ module RubyEventStore
|
|
10
10
|
dispatcher: Dispatcher.new,
|
11
11
|
clock: default_clock,
|
12
12
|
correlation_id_generator: default_correlation_id_generator)
|
13
|
+
|
14
|
+
|
13
15
|
@repository = repository
|
14
16
|
@mapper = mapper
|
17
|
+
@subscriptions = subscriptions
|
15
18
|
@broker = Broker.new(subscriptions: subscriptions, dispatcher: dispatcher)
|
16
19
|
@clock = clock
|
17
20
|
@metadata = Concurrent::ThreadLocalVar.new
|
@@ -21,20 +24,20 @@ module RubyEventStore
|
|
21
24
|
|
22
25
|
# Persists events and notifies subscribed handlers about them
|
23
26
|
#
|
24
|
-
# @param events [Array<Event
|
27
|
+
# @param events [Array<Event>, Event] event(s)
|
25
28
|
# @param stream_name [String] name of the stream for persisting events.
|
26
29
|
# @param expected_version [:any, :auto, :none, Integer] controls optimistic locking strategy. {http://railseventstore.org/docs/expected_version/ Read more}
|
27
30
|
# @return [self]
|
28
31
|
def publish(events, stream_name: GLOBAL_STREAM, expected_version: :any)
|
29
32
|
enriched_events = enrich_events_metadata(events)
|
30
|
-
|
31
|
-
|
32
|
-
enriched_events.zip(
|
33
|
+
records = transform(enriched_events)
|
34
|
+
append_records_to_stream(records, stream_name: stream_name, expected_version: expected_version)
|
35
|
+
enriched_events.zip(records) do |event, record|
|
33
36
|
with_metadata(
|
34
37
|
correlation_id: event.metadata.fetch(:correlation_id),
|
35
38
|
causation_id: event.event_id,
|
36
39
|
) do
|
37
|
-
broker.(event,
|
40
|
+
broker.(event, record)
|
38
41
|
end
|
39
42
|
end
|
40
43
|
self
|
@@ -45,8 +48,11 @@ module RubyEventStore
|
|
45
48
|
# @param (see #publish)
|
46
49
|
# @return [self]
|
47
50
|
def append(events, stream_name: GLOBAL_STREAM, expected_version: :any)
|
48
|
-
|
49
|
-
|
51
|
+
append_records_to_stream(
|
52
|
+
transform(enrich_events_metadata(events)),
|
53
|
+
stream_name: stream_name,
|
54
|
+
expected_version: expected_version
|
55
|
+
)
|
50
56
|
self
|
51
57
|
end
|
52
58
|
|
@@ -58,7 +64,7 @@ module RubyEventStore
|
|
58
64
|
# @param expected_version (see #publish)
|
59
65
|
# @return [self]
|
60
66
|
def link(event_ids, stream_name:, expected_version: :any)
|
61
|
-
repository.link_to_stream(event_ids, Stream.new(stream_name), ExpectedVersion.new(expected_version))
|
67
|
+
repository.link_to_stream(Array(event_ids), Stream.new(stream_name), ExpectedVersion.new(expected_version))
|
62
68
|
self
|
63
69
|
end
|
64
70
|
|
@@ -121,6 +127,14 @@ module RubyEventStore
|
|
121
127
|
broker.add_global_subscription(subscriber || proc)
|
122
128
|
end
|
123
129
|
|
130
|
+
# Get list of handlers subscribed to an event
|
131
|
+
#
|
132
|
+
# @param to [Class, String] type of events to get list of sybscribed handlers
|
133
|
+
# @return [Array<Object, Class>]
|
134
|
+
def subscribers_for(event_type)
|
135
|
+
subscriptions.all_for(event_type)
|
136
|
+
end
|
137
|
+
|
124
138
|
# Builder object for collecting temporary handlers (subscribers)
|
125
139
|
# which are active only during the invocation of the provided
|
126
140
|
# block of code.
|
@@ -222,9 +236,22 @@ module RubyEventStore
|
|
222
236
|
# Deserialize event which was serialized for async event handlers
|
223
237
|
# {http://railseventstore.org/docs/subscribe/#async-handlers Read more}
|
224
238
|
#
|
225
|
-
# @return [Event
|
226
|
-
def deserialize(event_type:, event_id:, data:, metadata:)
|
227
|
-
|
239
|
+
# @return [Event] deserialized event
|
240
|
+
def deserialize(serializer:, event_type:, event_id:, data:, metadata:, timestamp: nil, valid_at: nil)
|
241
|
+
extract_timestamp = lambda do |m|
|
242
|
+
(m[:timestamp] || Time.parse(m.fetch('timestamp'))).iso8601
|
243
|
+
end
|
244
|
+
|
245
|
+
mapper.record_to_event(
|
246
|
+
SerializedRecord.new(
|
247
|
+
event_type: event_type,
|
248
|
+
event_id: event_id,
|
249
|
+
data: data,
|
250
|
+
metadata: metadata,
|
251
|
+
timestamp: timestamp || timestamp_ = extract_timestamp[serializer.load(metadata)],
|
252
|
+
valid_at: valid_at || timestamp_,
|
253
|
+
).deserialize(serializer)
|
254
|
+
)
|
228
255
|
end
|
229
256
|
|
230
257
|
# Read additional metadata which will be added for published events
|
@@ -262,12 +289,10 @@ module RubyEventStore
|
|
262
289
|
# end
|
263
290
|
# event_store.overwrite(events)
|
264
291
|
#
|
265
|
-
# @param events [Array<Event
|
292
|
+
# @param events [Array<Event>, Event] event(s) to serialize and overwrite again
|
266
293
|
# @return [self]
|
267
294
|
def overwrite(events_or_event)
|
268
|
-
|
269
|
-
serialized_events = serialize_events(events)
|
270
|
-
repository.update_messages(serialized_events)
|
295
|
+
repository.update_messages(transform(Array(events_or_event)))
|
271
296
|
self
|
272
297
|
end
|
273
298
|
|
@@ -280,10 +305,8 @@ module RubyEventStore
|
|
280
305
|
|
281
306
|
private
|
282
307
|
|
283
|
-
def
|
284
|
-
events.map
|
285
|
-
mapper.event_to_serialized_record(ev)
|
286
|
-
end
|
308
|
+
def transform(events)
|
309
|
+
events.map { |ev| mapper.event_to_record(ev) }
|
287
310
|
end
|
288
311
|
|
289
312
|
def enrich_events_metadata(events)
|
@@ -295,11 +318,12 @@ module RubyEventStore
|
|
295
318
|
def enrich_event_metadata(event)
|
296
319
|
metadata.each { |key, value| event.metadata[key] ||= value }
|
297
320
|
event.metadata[:timestamp] ||= clock.call
|
321
|
+
event.metadata[:valid_at] ||= event.metadata.fetch(:timestamp)
|
298
322
|
event.metadata[:correlation_id] ||= correlation_id_generator.call
|
299
323
|
end
|
300
324
|
|
301
|
-
def
|
302
|
-
repository.append_to_stream(
|
325
|
+
def append_records_to_stream(records, stream_name:, expected_version:)
|
326
|
+
repository.append_to_stream(records, Stream.new(stream_name), ExpectedVersion.new(expected_version))
|
303
327
|
end
|
304
328
|
|
305
329
|
protected
|
@@ -309,13 +333,13 @@ module RubyEventStore
|
|
309
333
|
end
|
310
334
|
|
311
335
|
def default_clock
|
312
|
-
->{ Time.now.utc }
|
336
|
+
->{ Time.now.utc.round(TIMESTAMP_PRECISION) }
|
313
337
|
end
|
314
338
|
|
315
339
|
def default_correlation_id_generator
|
316
340
|
->{ SecureRandom.uuid }
|
317
341
|
end
|
318
342
|
|
319
|
-
attr_reader :repository, :mapper, :broker, :clock, :correlation_id_generator
|
343
|
+
attr_reader :repository, :mapper, :subscriptions, :broker, :clock, :correlation_id_generator
|
320
344
|
end
|
321
345
|
end
|
@@ -6,10 +6,10 @@ module RubyEventStore
|
|
6
6
|
@dispatchers = dispatchers
|
7
7
|
end
|
8
8
|
|
9
|
-
def call(subscriber, event,
|
9
|
+
def call(subscriber, event, record)
|
10
10
|
@dispatchers.each do |dispatcher|
|
11
11
|
if dispatcher.verify(subscriber)
|
12
|
-
dispatcher.call(subscriber, event,
|
12
|
+
dispatcher.call(subscriber, event, record)
|
13
13
|
break
|
14
14
|
end
|
15
15
|
end
|
@@ -41,6 +41,13 @@ module RubyEventStore
|
|
41
41
|
metadata[:timestamp]
|
42
42
|
end
|
43
43
|
|
44
|
+
# Validity time from metadata
|
45
|
+
#
|
46
|
+
# @return [Time, nil]
|
47
|
+
def valid_at
|
48
|
+
metadata[:valid_at]
|
49
|
+
end
|
50
|
+
|
44
51
|
# Two events are equal if:
|
45
52
|
# * they are of the same class
|
46
53
|
# * have identical event id
|
@@ -116,7 +123,7 @@ module RubyEventStore
|
|
116
123
|
# on correlation_id and message_id of the provided message.
|
117
124
|
# {http://railseventstore.org/docs/correlation_causation/ Find out more}
|
118
125
|
#
|
119
|
-
# @param other_message [Event,
|
126
|
+
# @param other_message [Event, command] message to correlate with. Most likely an event or a command. Must respond to correlation_id and message_id.
|
120
127
|
# @return [String] set causation_id
|
121
128
|
def correlate_with(other_message)
|
122
129
|
self.correlation_id = other_message.correlation_id || other_message.message_id
|
@@ -4,19 +4,40 @@ require 'ostruct'
|
|
4
4
|
module RubyEventStore
|
5
5
|
class InMemoryRepository
|
6
6
|
|
7
|
-
def initialize
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
7
|
+
def initialize(serializer: NULL)
|
8
|
+
@serializer = serializer
|
9
|
+
@streams = Hash.new { |h, k| h[k] = Array.new }
|
10
|
+
@mutex = Mutex.new
|
11
|
+
@storage = Hash.new
|
11
12
|
end
|
12
13
|
|
13
|
-
def append_to_stream(
|
14
|
-
|
14
|
+
def append_to_stream(records, stream, expected_version)
|
15
|
+
serialized_records = records.map { |record| record.serialize(serializer) }
|
16
|
+
|
17
|
+
with_synchronize(expected_version, stream) do |resolved_version|
|
18
|
+
raise WrongExpectedEventVersion unless last_stream_version(stream).equal?(resolved_version)
|
19
|
+
|
20
|
+
serialized_records.each do |serialized_record|
|
21
|
+
raise EventDuplicatedInStream if has_event?(serialized_record.event_id)
|
22
|
+
storage[serialized_record.event_id] = serialized_record
|
23
|
+
streams[stream.name] << serialized_record.event_id
|
24
|
+
end
|
25
|
+
end
|
26
|
+
self
|
15
27
|
end
|
16
28
|
|
17
29
|
def link_to_stream(event_ids, stream, expected_version)
|
18
|
-
|
19
|
-
|
30
|
+
serialized_records = event_ids.map { |id| read_event(id) }
|
31
|
+
|
32
|
+
with_synchronize(expected_version, stream) do |resolved_version|
|
33
|
+
raise WrongExpectedEventVersion unless last_stream_version(stream).equal?(resolved_version)
|
34
|
+
|
35
|
+
serialized_records.each do |serialized_record|
|
36
|
+
raise EventDuplicatedInStream if has_event_in_stream?(serialized_record.event_id, stream.name)
|
37
|
+
streams[stream.name] << serialized_record.event_id
|
38
|
+
end
|
39
|
+
end
|
40
|
+
self
|
20
41
|
end
|
21
42
|
|
22
43
|
def delete_stream(stream)
|
@@ -24,24 +45,34 @@ module RubyEventStore
|
|
24
45
|
end
|
25
46
|
|
26
47
|
def has_event?(event_id)
|
27
|
-
|
48
|
+
storage.has_key?(event_id)
|
28
49
|
end
|
29
50
|
|
30
51
|
def last_stream_event(stream)
|
31
|
-
|
52
|
+
last_id = event_ids_of_stream(stream).last
|
53
|
+
storage.fetch(last_id).deserialize(serializer) if last_id
|
32
54
|
end
|
33
55
|
|
34
56
|
def read(spec)
|
35
|
-
|
57
|
+
serialized_records = read_scope(spec)
|
36
58
|
if spec.batched?
|
37
|
-
batch_reader = ->(offset, limit)
|
38
|
-
|
59
|
+
batch_reader = ->(offset, limit) do
|
60
|
+
serialized_records
|
61
|
+
.drop(offset)
|
62
|
+
.take(limit)
|
63
|
+
.map { |serialized_record| serialized_record.deserialize(serializer) }
|
64
|
+
end
|
65
|
+
BatchEnumerator.new(spec.batch_size, serialized_records.size, batch_reader).each
|
39
66
|
elsif spec.first?
|
40
|
-
|
67
|
+
serialized_records.first&.deserialize(serializer)
|
41
68
|
elsif spec.last?
|
42
|
-
|
69
|
+
serialized_records.last&.deserialize(serializer)
|
43
70
|
else
|
44
|
-
|
71
|
+
Enumerator.new do |y|
|
72
|
+
serialized_records.each do |serialized_record|
|
73
|
+
y << serialized_record.deserialize(serializer)
|
74
|
+
end
|
75
|
+
end
|
45
76
|
end
|
46
77
|
end
|
47
78
|
|
@@ -49,53 +80,73 @@ module RubyEventStore
|
|
49
80
|
read_scope(spec).count
|
50
81
|
end
|
51
82
|
|
52
|
-
def update_messages(
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
83
|
+
def update_messages(records)
|
84
|
+
records.each do |record|
|
85
|
+
read_event(record.event_id)
|
86
|
+
serialized_record =
|
87
|
+
Record.new(
|
88
|
+
event_id: record.event_id,
|
89
|
+
event_type: record.event_type,
|
90
|
+
data: record.data,
|
91
|
+
metadata: record.metadata,
|
92
|
+
timestamp: Time.iso8601(storage.fetch(record.event_id).timestamp),
|
93
|
+
valid_at: record.valid_at,
|
94
|
+
).serialize(serializer)
|
95
|
+
storage[record.event_id] = serialized_record
|
61
96
|
end
|
62
97
|
end
|
63
98
|
|
64
99
|
def streams_of(event_id)
|
65
|
-
streams
|
66
|
-
|
67
|
-
|
100
|
+
streams
|
101
|
+
.select { |name,| has_event_in_stream?(event_id, name) }
|
102
|
+
.map { |name,| Stream.new(name) }
|
68
103
|
end
|
69
104
|
|
70
105
|
private
|
71
106
|
def read_scope(spec)
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
107
|
+
serialized_records = serialized_records_of_stream(spec.stream)
|
108
|
+
serialized_records = ordered(serialized_records, spec)
|
109
|
+
serialized_records = serialized_records.select{|e| spec.with_ids.any?{|x| x.eql?(e.event_id)}} if spec.with_ids?
|
110
|
+
serialized_records = serialized_records.select{|e| spec.with_types.any?{|x| x.eql?(e.event_type)}} if spec.with_types?
|
111
|
+
serialized_records = serialized_records.reverse if spec.backward?
|
112
|
+
serialized_records = serialized_records.drop(index_of(serialized_records, spec.start) + 1) if spec.start
|
113
|
+
serialized_records = serialized_records.take(index_of(serialized_records, spec.stop)) if spec.stop
|
114
|
+
serialized_records = serialized_records.take(spec.limit) if spec.limit?
|
115
|
+
serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) < spec.older_than } if spec.older_than
|
116
|
+
serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) <= spec.older_than_or_equal } if spec.older_than_or_equal
|
117
|
+
serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) > spec.newer_than } if spec.newer_than
|
118
|
+
serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) >= spec.newer_than_or_equal } if spec.newer_than_or_equal
|
119
|
+
serialized_records
|
80
120
|
end
|
81
121
|
|
82
122
|
def read_event(event_id)
|
83
|
-
|
123
|
+
storage.fetch(event_id) { raise EventNotFound.new(event_id) }
|
84
124
|
end
|
85
125
|
|
86
|
-
def
|
87
|
-
streams.fetch(name, Array.new)
|
126
|
+
def event_ids_of_stream(stream)
|
127
|
+
streams.fetch(stream.name, Array.new)
|
88
128
|
end
|
89
129
|
|
90
|
-
def
|
91
|
-
|
130
|
+
def serialized_records_of_stream(stream)
|
131
|
+
stream.global? ? storage.values : storage.fetch_values(*event_ids_of_stream(stream))
|
132
|
+
end
|
133
|
+
|
134
|
+
def ordered(serialized_records, spec)
|
135
|
+
case spec.time_sort_by
|
136
|
+
when :as_at
|
137
|
+
serialized_records.sort_by(&:timestamp)
|
138
|
+
when :as_of
|
139
|
+
serialized_records.sort_by(&:valid_at)
|
140
|
+
else
|
141
|
+
serialized_records
|
142
|
+
end
|
92
143
|
end
|
93
144
|
|
94
145
|
def last_stream_version(stream)
|
95
|
-
|
146
|
+
event_ids_of_stream(stream).size - 1
|
96
147
|
end
|
97
148
|
|
98
|
-
def
|
149
|
+
def with_synchronize(expected_version, stream, &block)
|
99
150
|
resolved_version = expected_version.resolve_for(stream, method(:last_stream_version))
|
100
151
|
|
101
152
|
# expected_version :auto assumes external lock is used
|
@@ -108,30 +159,18 @@ module RubyEventStore
|
|
108
159
|
Thread.pass
|
109
160
|
mutex.synchronize do
|
110
161
|
resolved_version = last_stream_version(stream) if expected_version.any?
|
111
|
-
|
162
|
+
block.call(resolved_version)
|
112
163
|
end
|
113
164
|
end
|
114
165
|
|
115
|
-
def
|
116
|
-
|
117
|
-
raise WrongExpectedEventVersion unless last_stream_version(stream).equal?(resolved_version)
|
118
|
-
|
119
|
-
events.each do |event|
|
120
|
-
raise EventDuplicatedInStream if stream_events.any? {|ev| ev.event_id.eql?(event.event_id)}
|
121
|
-
if include_global
|
122
|
-
raise EventDuplicatedInStream if has_event?(event.event_id)
|
123
|
-
global.push(event)
|
124
|
-
end
|
125
|
-
stream_events.push(event)
|
126
|
-
end
|
127
|
-
streams[stream.name] = stream_events
|
128
|
-
self
|
166
|
+
def has_event_in_stream?(event_id, stream_name)
|
167
|
+
streams.fetch(stream_name, Array.new).any? { |id| id.eql?(event_id) }
|
129
168
|
end
|
130
169
|
|
131
170
|
def index_of(source, event_id)
|
132
171
|
source.index {|item| item.event_id.eql?(event_id)}
|
133
172
|
end
|
134
173
|
|
135
|
-
attr_reader :streams, :mutex, :
|
174
|
+
attr_reader :streams, :mutex, :storage, :serializer
|
136
175
|
end
|
137
176
|
end
|