synapse-core 0.2.0 → 0.4.0
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.
- data/lib/synapse.rb +3 -0
- data/lib/synapse/command/simple_command_bus.rb +2 -2
- data/lib/synapse/common/concurrency/identifier_lock.rb +71 -0
- data/lib/synapse/common/concurrency/public_lock.rb +96 -0
- data/lib/synapse/event_bus/simple_event_bus.rb +1 -1
- data/lib/synapse/event_bus/wiring.rb +0 -4
- data/lib/synapse/event_sourcing/member.rb +0 -4
- data/lib/synapse/event_sourcing/snapshot/count_trigger.rb +2 -2
- data/lib/synapse/event_store.rb +1 -9
- data/lib/synapse/partitioning.rb +0 -2
- data/lib/synapse/process_manager.rb +12 -0
- data/lib/synapse/process_manager/lock_manager.rb +22 -0
- data/lib/synapse/process_manager/pessimistic_lock_manager.rb +23 -0
- data/lib/synapse/process_manager/process.rb +2 -0
- data/lib/synapse/process_manager/process_factory.rb +52 -0
- data/lib/synapse/process_manager/process_manager.rb +170 -0
- data/lib/synapse/process_manager/process_repository.rb +53 -0
- data/lib/synapse/process_manager/repository/in_memory.rb +63 -0
- data/lib/synapse/process_manager/resource_injector.rb +12 -0
- data/lib/synapse/process_manager/simple_process_manager.rb +48 -0
- data/lib/synapse/process_manager/wiring/process.rb +27 -0
- data/lib/synapse/process_manager/wiring/process_manager.rb +72 -0
- data/lib/synapse/repository.rb +1 -0
- data/lib/synapse/repository/locking.rb +1 -1
- data/lib/synapse/repository/optimistic_lock_manager.rb +128 -0
- data/lib/synapse/repository/pessimistic_lock_manager.rb +4 -37
- data/lib/synapse/serialization.rb +1 -1
- data/lib/synapse/serialization/{converter/factory.rb → converter_factory.rb} +0 -0
- data/lib/synapse/serialization/serializer.rb +5 -3
- data/lib/synapse/uow/listener_collection.rb +59 -1
- data/lib/synapse/version.rb +1 -1
- data/lib/synapse/wiring/message_wiring.rb +7 -3
- data/lib/synapse/wiring/wire.rb +7 -2
- data/test/common/concurrency/identifier_lock_test.rb +36 -0
- data/test/common/concurrency/public_lock_test.rb +83 -0
- data/test/partitioning/packing/json_test.rb +2 -1
- data/test/process_manager/in_memory_test.rb +57 -0
- data/test/process_manager/process_factory_test.rb +31 -0
- data/test/process_manager/simple_process_manager_test.rb +130 -0
- data/test/process_manager/wiring/fixtures.rb +42 -0
- data/test/process_manager/wiring/process_manager_test.rb +73 -0
- data/test/process_manager/wiring/process_test.rb +35 -0
- data/test/repository/optimistic_test.rb +41 -0
- data/test/repository/pessimistic_test.rb +20 -0
- data/test/serialization/converter/chain_test.rb +31 -0
- data/test/serialization/lazy_object_test.rb +1 -1
- data/test/serialization/message/serialization_aware_message_test.rb +4 -2
- data/test/serialization/message/serialized_message_builder_test.rb +1 -1
- data/test/serialization/message/serialized_message_test.rb +3 -2
- data/test/serialization/serializer/marshal_test.rb +1 -1
- data/test/serialization/serializer/oj_test.rb +1 -1
- data/test/serialization/serializer/ox_test.rb +1 -1
- data/test/serialization/serializer_test.rb +1 -1
- data/test/test_ext.rb +5 -2
- data/test/wiring/wire_registry_test.rb +10 -10
- data/test/wiring/wire_test.rb +5 -5
- metadata +29 -16
- data/lib/synapse/event_store/mongo.rb +0 -8
- data/lib/synapse/event_store/mongo/cursor_event_stream.rb +0 -63
- data/lib/synapse/event_store/mongo/event_store.rb +0 -86
- data/lib/synapse/event_store/mongo/per_commit_strategy.rb +0 -253
- data/lib/synapse/event_store/mongo/per_event_strategy.rb +0 -143
- data/lib/synapse/event_store/mongo/storage_strategy.rb +0 -113
- data/lib/synapse/event_store/mongo/template.rb +0 -73
- data/lib/synapse/partitioning/amqp.rb +0 -3
- data/lib/synapse/partitioning/amqp/amqp_queue_reader.rb +0 -50
- data/lib/synapse/partitioning/amqp/amqp_queue_writer.rb +0 -31
- data/lib/synapse/partitioning/amqp/key_resolver.rb +0 -26
- data/lib/synapse/serialization/converter/bson.rb +0 -28
@@ -23,9 +23,9 @@ module Synapse
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
require 'synapse/serialization/converter_factory'
|
26
27
|
require 'synapse/serialization/converter'
|
27
28
|
require 'synapse/serialization/converter/chain'
|
28
|
-
require 'synapse/serialization/converter/factory'
|
29
29
|
require 'synapse/serialization/converter/identity'
|
30
30
|
|
31
31
|
require 'synapse/serialization/errors'
|
File without changes
|
@@ -4,13 +4,15 @@ module Synapse
|
|
4
4
|
# @abstract
|
5
5
|
class Serializer
|
6
6
|
# @return [ConverterFactory]
|
7
|
-
|
7
|
+
attr_reader :converter_factory
|
8
8
|
|
9
9
|
# @return [RevisionResolver]
|
10
10
|
attr_accessor :revision_resolver
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
# @param [ConverterFactory] converter_factory
|
13
|
+
# @return [undefined]
|
14
|
+
def initialize(converter_factory)
|
15
|
+
@converter_factory = converter_factory
|
14
16
|
end
|
15
17
|
|
16
18
|
# @param [Object] object
|
@@ -14,6 +14,7 @@ module Synapse
|
|
14
14
|
class UnitOfWorkListenerCollection < UnitOfWorkListener
|
15
15
|
def initialize
|
16
16
|
@listeners = Array.new
|
17
|
+
@logger = Logging.logger[self.class]
|
17
18
|
end
|
18
19
|
|
19
20
|
# Pushes a unit of work listener onto the end of this collection
|
@@ -21,6 +22,10 @@ module Synapse
|
|
21
22
|
# @param [UnitOfWorkListener] listener
|
22
23
|
# @return [undefined]
|
23
24
|
def push(listener)
|
25
|
+
if @logger.debug?
|
26
|
+
@logger.debug 'Registering listener [%s]' % listener.class
|
27
|
+
end
|
28
|
+
|
24
29
|
@listeners.push listener
|
25
30
|
end
|
26
31
|
|
@@ -29,9 +34,17 @@ module Synapse
|
|
29
34
|
# @param [UnitOfWork] unit
|
30
35
|
# @return [undefined]
|
31
36
|
def on_start(unit)
|
37
|
+
@logger.debug 'Notifying listeners that unit of work is starting'
|
38
|
+
|
32
39
|
@listeners.each do |listener|
|
40
|
+
if @logger.debug?
|
41
|
+
@logger.debug 'Notifying [%s] of start' % listener.class
|
42
|
+
end
|
43
|
+
|
33
44
|
listener.on_start unit
|
34
45
|
end
|
46
|
+
|
47
|
+
@logger.debug 'Listeners successfully notified'
|
35
48
|
end
|
36
49
|
|
37
50
|
# @param [UnitOfWork] unit
|
@@ -50,43 +63,88 @@ module Synapse
|
|
50
63
|
# @param [Hash<EventBus, Array>] events
|
51
64
|
# @return [undefined]
|
52
65
|
def on_prepare_commit(unit, aggregates, events)
|
66
|
+
@logger.debug 'Notifying listeners that commit was requested'
|
67
|
+
|
53
68
|
@listeners.each do |listener|
|
69
|
+
if @logger.debug?
|
70
|
+
@logger.debug 'Notifying [%s] of commit' % listener.class
|
71
|
+
end
|
72
|
+
|
54
73
|
listener.on_prepare_commit unit, aggregates, events
|
55
74
|
end
|
75
|
+
|
76
|
+
@logger.debug 'Listeners successfully notified'
|
56
77
|
end
|
57
78
|
|
58
79
|
# @param [UnitOfWork] unit
|
59
80
|
# @param [Object] transaction
|
60
81
|
# @return [undefined]
|
61
82
|
def on_prepare_transaction_commit(unit, transaction)
|
83
|
+
@logger.debug 'Notifying listeners that transactional commit was requested'
|
84
|
+
|
62
85
|
@listeners.each do |listener|
|
86
|
+
if @logger.debug?
|
87
|
+
@logger.debug 'Notifying [%s] of transactional commit' % listener.class
|
88
|
+
end
|
89
|
+
|
63
90
|
listener.on_prepare_transaction_commit unit, transaction
|
64
91
|
end
|
92
|
+
|
93
|
+
@logger.debug 'Listeners successfully notified'
|
65
94
|
end
|
66
95
|
|
67
96
|
# @param [UnitOfWork] unit
|
68
97
|
# @return [undefined]
|
69
98
|
def after_commit(unit)
|
99
|
+
@logger.debug 'Notifying listeners that commit has finished'
|
100
|
+
|
70
101
|
@listeners.reverse_each do |listener|
|
102
|
+
if @logger.debug?
|
103
|
+
@logger.debug 'Notifying [%s] of finished commit' % listener.class
|
104
|
+
end
|
105
|
+
|
71
106
|
listener.after_commit unit
|
72
107
|
end
|
108
|
+
|
109
|
+
@logger.debug 'Listeners successfully notified'
|
73
110
|
end
|
74
111
|
|
75
112
|
# @param [UnitOfWork] unit
|
76
113
|
# @param [Error] cause
|
77
114
|
# @return [undefined]
|
78
115
|
def on_rollback(unit, cause = nil)
|
116
|
+
@logger.debug 'Notifying listeners of rollback'
|
117
|
+
|
79
118
|
@listeners.reverse_each do |listener|
|
119
|
+
if @logger.debug?
|
120
|
+
@logger.debug 'Notifying [%s] of rollback' % listener.class
|
121
|
+
end
|
122
|
+
|
80
123
|
listener.on_rollback unit, cause
|
81
124
|
end
|
125
|
+
|
126
|
+
@logger.debug 'Listeners successfully notified'
|
82
127
|
end
|
83
128
|
|
84
129
|
# @param [UnitOfWork] unit
|
85
130
|
# @return [undefined]
|
86
131
|
def on_cleanup(unit)
|
132
|
+
@logger.debug 'Notifying listeners of cleanup'
|
133
|
+
|
87
134
|
@listeners.reverse_each do |listener|
|
88
|
-
|
135
|
+
if @logger.debug?
|
136
|
+
@logger.debug 'Notifying [%s] of cleanup' % listener.class
|
137
|
+
end
|
138
|
+
|
139
|
+
begin
|
140
|
+
listener.on_cleanup unit
|
141
|
+
rescue => exception
|
142
|
+
# Ignore this exception so that we can continue cleaning up
|
143
|
+
@logger.warn 'Listener raised an exception during cleanup: %s' % exception.inspect
|
144
|
+
end
|
89
145
|
end
|
146
|
+
|
147
|
+
@logger.debug 'Listeners successfully notified'
|
90
148
|
end
|
91
149
|
end
|
92
150
|
end
|
data/lib/synapse/version.rb
CHANGED
@@ -8,21 +8,25 @@ module Synapse
|
|
8
8
|
included do
|
9
9
|
# @return [WireRegistry]
|
10
10
|
class_attribute :wire_registry
|
11
|
+
|
12
|
+
# By default, the wire registry allows duplicates
|
13
|
+
self.wire_registry = Wiring::WireRegistry.new true
|
11
14
|
end
|
12
15
|
|
13
16
|
module ClassMethods
|
14
17
|
def wire(type, *args, &block)
|
15
18
|
options = args.extract_options!
|
16
19
|
|
17
|
-
|
20
|
+
to = options.delete :to
|
21
|
+
unless to
|
18
22
|
unless block
|
19
23
|
raise ArgumentError, 'Expected block or option :to'
|
20
24
|
end
|
21
25
|
|
22
|
-
|
26
|
+
to = block
|
23
27
|
end
|
24
28
|
|
25
|
-
wire = Wire.new type, options
|
29
|
+
wire = Wire.new type, options, to
|
26
30
|
|
27
31
|
self.wire_registry.register wire
|
28
32
|
end
|
data/lib/synapse/wiring/wire.rb
CHANGED
@@ -11,11 +11,16 @@ module Synapse
|
|
11
11
|
# @return [Object] Either a method symbol or block
|
12
12
|
attr_reader :handler
|
13
13
|
|
14
|
+
# @return [Hash] Options specific to the component being wired
|
15
|
+
attr_reader :options
|
16
|
+
|
14
17
|
# @param [Class] type
|
18
|
+
# @param [Hash] options
|
15
19
|
# @param [Object] handler Either a method symbol or block
|
16
|
-
# @return [undefined]
|
17
|
-
def initialize(type, handler)
|
20
|
+
# @return [undefined]
|
21
|
+
def initialize(type, options, handler)
|
18
22
|
@type = type
|
23
|
+
@options = options
|
19
24
|
@handler = handler
|
20
25
|
end
|
21
26
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Synapse
|
4
|
+
class IdentifierLockTest < Test::Unit::TestCase
|
5
|
+
def test_disposal
|
6
|
+
lock = IdentifierLock.new
|
7
|
+
identifier = 'some_id'
|
8
|
+
|
9
|
+
lock.obtain_lock identifier
|
10
|
+
lock.release_lock identifier
|
11
|
+
|
12
|
+
identifiers = lock.instance_variable_get :@identifiers
|
13
|
+
refute identifiers.has_key? identifier
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_owned?
|
17
|
+
lock = IdentifierLock.new
|
18
|
+
identifier = 'some_id'
|
19
|
+
|
20
|
+
refute lock.owned? identifier
|
21
|
+
|
22
|
+
lock.obtain_lock identifier
|
23
|
+
assert lock.owned? identifier
|
24
|
+
|
25
|
+
lock.release_lock identifier
|
26
|
+
refute lock.owned? identifier
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_release_lock
|
30
|
+
lock = IdentifierLock.new
|
31
|
+
assert_raise ThreadError do
|
32
|
+
lock.release_lock 'derp'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Synapse
|
4
|
+
class PublicLockTest < Test::Unit::TestCase
|
5
|
+
def test_lock_raises
|
6
|
+
@lock = PublicLock.new
|
7
|
+
@lock.lock
|
8
|
+
|
9
|
+
assert_raise ThreadError do
|
10
|
+
@lock.lock
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_lock_removes_waiting
|
15
|
+
@lock = PublicLock.new
|
16
|
+
@lock.lock
|
17
|
+
|
18
|
+
t = Thread.new do
|
19
|
+
@lock.lock
|
20
|
+
end
|
21
|
+
|
22
|
+
wait_until do
|
23
|
+
@lock.waiting == [t]
|
24
|
+
end
|
25
|
+
|
26
|
+
t.kill
|
27
|
+
|
28
|
+
wait_until do
|
29
|
+
@lock.waiting == []
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_synchronize
|
34
|
+
@lock = PublicLock.new
|
35
|
+
|
36
|
+
refute @lock.owned?
|
37
|
+
refute @lock.owned_by? Thread.current
|
38
|
+
|
39
|
+
@lock.synchronize do
|
40
|
+
assert @lock.owned?
|
41
|
+
assert @lock.owned_by? Thread.current
|
42
|
+
end
|
43
|
+
|
44
|
+
refute @lock.owned?
|
45
|
+
refute @lock.owned_by? Thread.current
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_unlock_raises
|
49
|
+
@lock = PublicLock.new
|
50
|
+
|
51
|
+
assert_raise ThreadError do
|
52
|
+
@lock.unlock
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_try_lock
|
57
|
+
@lock = PublicLock.new
|
58
|
+
|
59
|
+
t = Thread.new do
|
60
|
+
assert @lock.try_lock
|
61
|
+
Thread.stop
|
62
|
+
@lock.unlock
|
63
|
+
end
|
64
|
+
|
65
|
+
wait_until do
|
66
|
+
@lock.owned_by? t
|
67
|
+
end
|
68
|
+
|
69
|
+
refute @lock.try_lock
|
70
|
+
|
71
|
+
t.wakeup
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_try_lock_raises
|
75
|
+
@lock = PublicLock.new
|
76
|
+
@lock.try_lock
|
77
|
+
|
78
|
+
assert_raise ThreadError do
|
79
|
+
@lock.try_lock
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -5,7 +5,8 @@ module Synapse
|
|
5
5
|
|
6
6
|
class JsonPackingTest < Test::Unit::TestCase
|
7
7
|
def setup
|
8
|
-
@
|
8
|
+
@converter_factory = Serialization::ConverterFactory.new
|
9
|
+
@serializer = Serialization::MarshalSerializer.new @converter_factory
|
9
10
|
@packer = JsonMessagePacker.new @serializer
|
10
11
|
@unpacker = JsonMessageUnpacker.new @serializer
|
11
12
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Synapse
|
4
|
+
module ProcessManager
|
5
|
+
|
6
|
+
class InMemoryProcessRepositoryTest < Test::Unit::TestCase
|
7
|
+
def test_find
|
8
|
+
correlation_a = Correlation.new :order_id, 1
|
9
|
+
correlation_b = Correlation.new :order_id, 2
|
10
|
+
|
11
|
+
process_a = Process.new
|
12
|
+
process_a.correlations.add correlation_a
|
13
|
+
process_b = Process.new
|
14
|
+
process_b.correlations.add correlation_b
|
15
|
+
|
16
|
+
repository = InMemoryProcessRepository.new
|
17
|
+
repository.add process_a
|
18
|
+
repository.add process_b
|
19
|
+
|
20
|
+
assert_equal [process_a.id], repository.find(Process, correlation_a)
|
21
|
+
assert_equal [process_b.id], repository.find(Process, correlation_b)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_load
|
25
|
+
repository = InMemoryProcessRepository.new
|
26
|
+
|
27
|
+
process_a = Process.new
|
28
|
+
process_b = Process.new
|
29
|
+
|
30
|
+
repository.add process_a
|
31
|
+
repository.add process_b
|
32
|
+
|
33
|
+
assert_equal process_a, repository.load(process_a.id)
|
34
|
+
assert_equal process_b, repository.load(process_b.id)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_commit
|
38
|
+
repository = InMemoryProcessRepository.new
|
39
|
+
|
40
|
+
process = Process.new
|
41
|
+
repository.commit process
|
42
|
+
|
43
|
+
assert_equal 1, repository.count
|
44
|
+
# Make sure the correlation set was marked as committed
|
45
|
+
assert_equal 0, process.correlations.additions.count
|
46
|
+
assert_equal 0, process.correlations.deletions.count
|
47
|
+
|
48
|
+
process.send :finish
|
49
|
+
|
50
|
+
repository.commit process
|
51
|
+
|
52
|
+
assert_equal 0, repository.count
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Synapse
|
4
|
+
module ProcessManager
|
5
|
+
class GenericProcessFactoryTest < Test::Unit::TestCase
|
6
|
+
def test_create
|
7
|
+
injector = Object.new
|
8
|
+
|
9
|
+
mock(injector).inject_resources(is_a(Process))
|
10
|
+
|
11
|
+
factory = GenericProcessFactory.new
|
12
|
+
factory.resource_injector = injector
|
13
|
+
|
14
|
+
process = factory.create Process
|
15
|
+
|
16
|
+
assert process.is_a? Process
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_supports
|
20
|
+
factory = GenericProcessFactory.new
|
21
|
+
|
22
|
+
assert factory.supports Process
|
23
|
+
refute factory.supports StubProcessWithArguments
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class StubProcessWithArguments < Process
|
28
|
+
def initialize(some_resource); end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Synapse
|
4
|
+
module ProcessManager
|
5
|
+
class SimpleProcessManagerTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@repository = InMemoryProcessRepository.new
|
8
|
+
@factory = GenericProcessFactory.new
|
9
|
+
@resolver = MetadataCorrelationResolver.new :order_id
|
10
|
+
@lock_manager = Object.new
|
11
|
+
@manager = SimpleProcessManager.new @repository, @factory, @lock_manager, @resolver, TestProcess
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_notify_new_process
|
15
|
+
@manager.optionally_create_events << CauseProcessCreationEvent
|
16
|
+
|
17
|
+
correlation = Correlation.new :order_id, 123
|
18
|
+
|
19
|
+
mock(@lock_manager).obtain_lock(is_a(String))
|
20
|
+
mock(@lock_manager).release_lock(is_a(String))
|
21
|
+
|
22
|
+
@manager.notify create_event 123, CauseProcessCreationEvent.new
|
23
|
+
|
24
|
+
assert_equal 1, @repository.count
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_notify_existing_process
|
28
|
+
process = TestProcess.new
|
29
|
+
process.correlations.add Correlation.new :order_id, 123
|
30
|
+
|
31
|
+
@repository.add process
|
32
|
+
|
33
|
+
mock(@lock_manager).obtain_lock(process.id)
|
34
|
+
mock(@lock_manager).release_lock(process.id)
|
35
|
+
|
36
|
+
@manager.notify create_event 123, CauseProcessNotificationEvent.new
|
37
|
+
|
38
|
+
assert_equal 1, @repository.count
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_notify_process_raises_but_suppressed
|
42
|
+
process = TestProcess.new
|
43
|
+
process.correlations.add Correlation.new :order_id, 123
|
44
|
+
|
45
|
+
@repository.add process
|
46
|
+
|
47
|
+
mock(@lock_manager).obtain_lock(process.id)
|
48
|
+
mock(@lock_manager).release_lock(process.id)
|
49
|
+
|
50
|
+
@manager.notify create_event 123, CauseProcessRaiseExceptionEvent.new
|
51
|
+
|
52
|
+
assert_equal 1, @repository.count
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_notify_process_raises
|
56
|
+
process = TestProcess.new
|
57
|
+
process.correlations.add Correlation.new :order_id, 123
|
58
|
+
|
59
|
+
@repository.add process
|
60
|
+
|
61
|
+
mock(@lock_manager).obtain_lock(process.id)
|
62
|
+
mock(@lock_manager).release_lock(process.id)
|
63
|
+
|
64
|
+
@manager.suppress_exceptions = false
|
65
|
+
|
66
|
+
assert_raise RuntimeError do
|
67
|
+
@manager.notify create_event 123, CauseProcessRaiseExceptionEvent.new
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_always_create
|
72
|
+
@manager.always_create_events << CauseProcessCreationEvent
|
73
|
+
|
74
|
+
correlation = Correlation.new :order_id, 123
|
75
|
+
|
76
|
+
# Lock is obtain/released for the 2 being created and once for the first being changed
|
77
|
+
mock(@lock_manager).obtain_lock(is_a(String)).times(3)
|
78
|
+
mock(@lock_manager).release_lock(is_a(String)).times(3)
|
79
|
+
|
80
|
+
@manager.notify create_event 123, CauseProcessCreationEvent.new
|
81
|
+
@manager.notify create_event 123, CauseProcessCreationEvent.new
|
82
|
+
|
83
|
+
assert_equal 2, @repository.count
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def create_event(order_id, event)
|
89
|
+
Domain::EventMessage.build do |builder|
|
90
|
+
builder.payload = event
|
91
|
+
builder.metadata = {
|
92
|
+
order_id: order_id
|
93
|
+
}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Example correlation resolver
|
99
|
+
class MetadataCorrelationResolver < CorrelationResolver
|
100
|
+
def initialize(property)
|
101
|
+
@property = property
|
102
|
+
end
|
103
|
+
|
104
|
+
def resolve(event)
|
105
|
+
value = event.metadata[@property]
|
106
|
+
if value
|
107
|
+
Correlation.new @property, value
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Test process that has all sorts of trigger events
|
113
|
+
class TestProcess < Process
|
114
|
+
attr_accessor :handled
|
115
|
+
|
116
|
+
def handle(event)
|
117
|
+
if event.payload_type == CauseProcessRaiseExceptionEvent
|
118
|
+
raise 'ohgodimnotgoodwithcomputers'
|
119
|
+
end
|
120
|
+
|
121
|
+
@handled ||= 0
|
122
|
+
@handled = @handled.next
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
class CauseProcessCreationEvent; end
|
127
|
+
class CauseProcessNotificationEvent; end
|
128
|
+
class CauseProcessRaiseExceptionEvent; end
|
129
|
+
end
|
130
|
+
end
|