synapse-core 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/lib/synapse/auditing/audit_logger.rb +28 -0
  2. data/lib/synapse/auditing/data_provider.rb +42 -0
  3. data/lib/synapse/auditing/dispatch_interceptor.rb +29 -0
  4. data/lib/synapse/auditing/unit_listener.rb +53 -0
  5. data/lib/synapse/auditing.rb +4 -0
  6. data/lib/synapse/command.rb +34 -0
  7. data/lib/synapse/{duplication.rb → common/duplication.rb} +0 -0
  8. data/lib/synapse/{errors.rb → common/errors.rb} +0 -0
  9. data/lib/synapse/{identifier.rb → common/identifier.rb} +2 -1
  10. data/lib/synapse/{message.rb → common/message.rb} +0 -0
  11. data/lib/synapse/{message_builder.rb → common/message_builder.rb} +0 -0
  12. data/lib/synapse/domain.rb +5 -0
  13. data/lib/synapse/event_bus.rb +5 -0
  14. data/lib/synapse/event_sourcing/conflict_resolver.rb +4 -6
  15. data/lib/synapse/event_sourcing/member.rb +11 -2
  16. data/lib/synapse/event_sourcing/snapshot/taker.rb +0 -18
  17. data/lib/synapse/event_sourcing.rb +13 -0
  18. data/lib/synapse/event_store/mongo/cursor_event_stream.rb +3 -3
  19. data/lib/synapse/event_store/mongo.rb +8 -0
  20. data/lib/synapse/event_store.rb +11 -0
  21. data/lib/synapse/partitioning/amqp/amqp_queue_reader.rb +50 -0
  22. data/lib/synapse/partitioning/amqp/amqp_queue_writer.rb +31 -0
  23. data/lib/synapse/partitioning/amqp/key_resolver.rb +26 -0
  24. data/lib/synapse/partitioning/amqp.rb +3 -0
  25. data/lib/synapse/partitioning/memory_queue_reader.rb +31 -0
  26. data/lib/synapse/partitioning/memory_queue_writer.rb +19 -0
  27. data/lib/synapse/partitioning/message_receipt.rb +25 -0
  28. data/lib/synapse/partitioning/packing/json_packer.rb +93 -0
  29. data/lib/synapse/partitioning/packing/json_unpacker.rb +83 -0
  30. data/lib/synapse/partitioning/packing.rb +27 -0
  31. data/lib/synapse/partitioning/queue_reader.rb +32 -0
  32. data/lib/synapse/partitioning/queue_writer.rb +17 -0
  33. data/lib/synapse/partitioning.rb +20 -0
  34. data/lib/synapse/process_manager.rb +4 -0
  35. data/lib/synapse/repository/locking.rb +3 -8
  36. data/lib/synapse/repository.rb +7 -0
  37. data/lib/synapse/serialization/converter/bson.rb +28 -0
  38. data/lib/synapse/serialization/serializer/attribute.rb +48 -0
  39. data/lib/synapse/serialization/serializer.rb +1 -1
  40. data/lib/synapse/serialization.rb +46 -0
  41. data/lib/synapse/uow/factory.rb +5 -5
  42. data/lib/synapse/uow/uow.rb +13 -13
  43. data/lib/synapse/uow.rb +8 -0
  44. data/lib/synapse/upcasting/chain.rb +1 -1
  45. data/lib/synapse/upcasting.rb +5 -0
  46. data/lib/synapse/version.rb +1 -1
  47. data/lib/synapse/wiring.rb +3 -0
  48. data/lib/synapse.rb +26 -338
  49. data/test/auditing/data_provider_test.rb +30 -0
  50. data/test/auditing/dispatch_interceptor_test.rb +25 -0
  51. data/test/auditing/unit_listener_test.rb +70 -0
  52. data/test/partitioning/memory_test.rb +34 -0
  53. data/test/partitioning/packing/json_test.rb +61 -0
  54. data/test/test_ext.rb +14 -0
  55. data/test/test_helper.rb +4 -0
  56. metadata +45 -24
  57. data/test/event_sourcing/snapshot/deferred_taker_test.rb +0 -19
@@ -0,0 +1,28 @@
1
+ module Synapse
2
+ module Auditing
3
+ # Represents a mechanism for auditing commands and the events produced by their execution
4
+ # @abstract
5
+ class AuditLogger
6
+ # Called when a command execution was finished successfully
7
+ #
8
+ # @abstract
9
+ # @param [CommandMessage] command
10
+ # @param [Object] return_value
11
+ # @param [Array<EventMessage>] events
12
+ # @return [undefined]
13
+ def on_success(command, return_value, events); end
14
+
15
+ # Called when a command execution results in an exception being raised
16
+ #
17
+ # The list of events may not be empty; in this case, some events could have been published
18
+ # to the event bus and/or appended to the event store.
19
+ #
20
+ # @abstract
21
+ # @param [CommandMessage] command
22
+ # @param [Exception] exception
23
+ # @param [Array<EventMessage>] events
24
+ # @return [undefined]
25
+ def on_failure(command, exception, events); end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,42 @@
1
+ module Synapse
2
+ module Auditing
3
+ # Provides relevant information to events for auditing purposes
4
+ # @abstract
5
+ class AuditDataProvider
6
+ # Returns auditing information for the given command
7
+ #
8
+ # @abstract
9
+ # @param [CommandMessage] command
10
+ # @return [Hash]
11
+ def provide_data_for(command); end
12
+ end
13
+
14
+ # Implementation of an audit provider that simply audits a command's metadata
15
+ class CommandMetadataProvider < AuditDataProvider
16
+ # @param [CommandMessage] command
17
+ # @return [Hash]
18
+ def provide_data_for(command)
19
+ command.metadata
20
+ end
21
+ end
22
+
23
+ # Implementation of an audit provider that attaches a command's identifier to each event
24
+ # produced as a result of the execution of that command
25
+ class CorrelationDataProvider < AuditDataProvider
26
+ # The default key to use when correlating events with commands
27
+ DEFAULT_KEY = :command_id
28
+
29
+ # @param [Symbol] correlation_key
30
+ # @return [undefined]
31
+ def initialize(correlation_key = DEFAULT_KEY)
32
+ @correlation_key = correlation_key
33
+ end
34
+
35
+ # @param [CommandMessage] command
36
+ # @return [Hash]
37
+ def provide_data_for(command)
38
+ Hash[@correlation_key, command.id]
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,29 @@
1
+ module Synapse
2
+ module Auditing
3
+ class AuditingDispatchInterceptor < Command::DispatchInterceptor
4
+ # @return [Array<AuditDataProvider>]
5
+ attr_accessor :data_providers
6
+
7
+ # @return [Array<AuditLogger>]
8
+ attr_accessor :loggers
9
+
10
+ def initialize
11
+ @data_providers = Array.new
12
+ @loggers = Array.new
13
+ end
14
+
15
+ # @param [CommandMessage] command
16
+ # @param [UnitOfWork] unit The current unit of work for this command dispatch
17
+ # @param [InterceptorChain] chain
18
+ # @return [Object] The result of the execution of the command
19
+ def intercept(command, unit, chain)
20
+ audit_listener = AuditingUnitOfWorkListener.new command, @data_providers, @loggers
21
+ unit.register_listener audit_listener
22
+
23
+ chain.proceed(command).tap do |result|
24
+ audit_listener.return_value = result
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,53 @@
1
+ module Synapse
2
+ module Auditing
3
+ class AuditingUnitOfWorkListener < UnitOfWork::UnitOfWorkListener
4
+ # @return [Array<EventMessage>]
5
+ attr_reader :recorded_events
6
+
7
+ # @return [Object]
8
+ attr_accessor :return_value
9
+
10
+ # @param [CommandMessage] command
11
+ # @param [Array<AuditDataProvider>] data_providers
12
+ # @param [Array<AuditLogger>] loggers
13
+ # @return [undefined]
14
+ def initialize(command, data_providers, loggers)
15
+ @command = command
16
+ @data_providers = data_providers
17
+ @loggers = loggers
18
+ @recorded_events = Array.new
19
+ end
20
+
21
+ # @param [UnitOfWork] unit
22
+ # @param [EventMessage] event
23
+ # @return [EventMessage]
24
+ def on_event_registered(unit, event)
25
+ audit_data = Hash.new
26
+ @data_providers.each do |provider|
27
+ audit_data.merge! provider.provide_data_for @command
28
+ end
29
+
30
+ event.and_metadata(audit_data).tap do |e|
31
+ @recorded_events.push e
32
+ end
33
+ end
34
+
35
+ # @param [UnitOfWork] unit
36
+ # @return [undefined]
37
+ def after_commit(unit)
38
+ @loggers.each do |logger|
39
+ logger.on_success @command, @return_value, @recorded_events
40
+ end
41
+ end
42
+
43
+ # @param [UnitOfWork] unit
44
+ # @param [Error] cause
45
+ # @return [undefined]
46
+ def on_rollback(unit, cause = nil)
47
+ @loggers.each do |logger|
48
+ logger.on_success @command, cause, @recorded_events
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,4 @@
1
+ require 'synapse/auditing/audit_logger'
2
+ require 'synapse/auditing/data_provider'
3
+ require 'synapse/auditing/dispatch_interceptor'
4
+ require 'synapse/auditing/unit_listener'
@@ -0,0 +1,34 @@
1
+ module Synapse
2
+ module Command
3
+ extend ActiveSupport::Autoload
4
+
5
+ # Optional filters and interceptors
6
+ autoload_at 'synapse/command/duplication' do
7
+ autoload :DuplicationFilter
8
+ autoload :DuplicationCleanupInterceptor
9
+ end
10
+
11
+ autoload_at 'synapse/command/filters/validation' do
12
+ autoload :ActiveModelValidationFilter
13
+ autoload :ActiveModelValidationError
14
+ end
15
+
16
+ autoload_at 'synapse/command/interceptors/serialization' do
17
+ autoload :SerializationOptimizingInterceptor
18
+ autoload :SerializationOptimizingListener
19
+ end
20
+ end
21
+ end
22
+
23
+ require 'synapse/command/command_bus'
24
+ require 'synapse/command/command_callback'
25
+ require 'synapse/command/command_filter'
26
+ require 'synapse/command/command_handler'
27
+ require 'synapse/command/dispatch_interceptor'
28
+ require 'synapse/command/errors'
29
+ require 'synapse/command/gateway'
30
+ require 'synapse/command/interceptor_chain'
31
+ require 'synapse/command/message'
32
+ require 'synapse/command/rollback_policy'
33
+ require 'synapse/command/simple_command_bus'
34
+ require 'synapse/command/wiring'
File without changes
@@ -19,5 +19,6 @@ module Synapse
19
19
  end
20
20
  end
21
21
 
22
- ActiveSupport.run_load_hooks :identifier_factory, IdentifierFactory
22
+ # Setup the default identifier factory
23
+ IdentifierFactory.instance = GuidIdentifierFactory.new
23
24
  end
File without changes
@@ -0,0 +1,5 @@
1
+ require 'synapse/domain/aggregate_root'
2
+ require 'synapse/domain/event_container'
3
+ require 'synapse/domain/message'
4
+ require 'synapse/domain/message_builder'
5
+ require 'synapse/domain/stream'
@@ -0,0 +1,5 @@
1
+ require 'synapse/event_bus/event_bus'
2
+ require 'synapse/event_bus/event_listener'
3
+ require 'synapse/event_bus/event_listener_proxy'
4
+ require 'synapse/event_bus/simple_event_bus'
5
+ require 'synapse/event_bus/wiring'
@@ -64,13 +64,11 @@ module Synapse
64
64
 
65
65
  # @return [DomainEventMessage]
66
66
  def next_event
67
- event = @delegate.next_event
68
-
69
- if @expected_version and event.sequence_number > @expected_version
70
- @unseen_events.push event
67
+ @delegate.next_event.tap do |event|
68
+ if @expected_version and event.sequence_number > @expected_version
69
+ @unseen_events.push event
70
+ end
71
71
  end
72
-
73
- event
74
72
  end
75
73
 
76
74
  # Delegators for domain event stream
@@ -4,6 +4,11 @@ module Synapse
4
4
  # applied to the aggregate
5
5
  module Member
6
6
  extend ActiveSupport::Concern
7
+ include Wiring::MessageWiring
8
+
9
+ included do
10
+ self.wire_registry = Wiring::WireRegistry.new true
11
+ end
7
12
 
8
13
  module ClassMethods
9
14
  # Registers an instance variable as a child entity
@@ -53,10 +58,14 @@ module Synapse
53
58
  # If the event is relative to this member, its parameters will be used to change
54
59
  # the state of this member
55
60
  #
56
- # @abstract
57
61
  # @param [EventMessage] event
58
62
  # @return [undefined]
59
- def handle_event(event); end
63
+ def handle_event(event)
64
+ wire = self.wire_registry.wire_for event.payload_type
65
+ if wire
66
+ invoke_wire event, wire
67
+ end
68
+ end
60
69
 
61
70
  private
62
71
 
@@ -17,24 +17,6 @@ module Synapse
17
17
  def schedule_snapshot(type_identifier, aggregate_id); end
18
18
  end
19
19
 
20
- # Snapshot taker that uses EventMachine to defer scheduling of snapshots
21
- class DeferredSnapshotTaker < SnapshotTaker
22
- # @param [SnapshotTaker] delegate
23
- # @return [undefined]
24
- def initialize(delegate)
25
- @delegate = delegate
26
- end
27
-
28
- # @param [String] type_identifier
29
- # @param [Object] aggregate_id
30
- # @return [undefined]
31
- def schedule_snapshot(type_identifier, aggregate_id)
32
- EventMachine.defer do
33
- @delegate.schedule_snapshot type_identifier, aggregate_id
34
- end
35
- end
36
- end
37
-
38
20
  # Snapshot taker that uses the actual aggregate and its state to create a snapshot event
39
21
  class AggregateSnapshotTaker < SnapshotTaker
40
22
  # @param [SnapshotEventStore] event_store
@@ -0,0 +1,13 @@
1
+ require 'synapse/event_sourcing/aggregate_factory'
2
+ require 'synapse/event_sourcing/conflict_resolver'
3
+ require 'synapse/event_sourcing/repository'
4
+ require 'synapse/event_sourcing/storage_listener'
5
+ require 'synapse/event_sourcing/stream_decorator'
6
+
7
+ require 'synapse/event_sourcing/member'
8
+ require 'synapse/event_sourcing/aggregate_root'
9
+ require 'synapse/event_sourcing/entity'
10
+
11
+ require 'synapse/event_sourcing/snapshot/count_stream'
12
+ require 'synapse/event_sourcing/snapshot/count_trigger'
13
+ require 'synapse/event_sourcing/snapshot/taker'
@@ -30,9 +30,9 @@ module Synapse
30
30
 
31
31
  # @return [DomainEventMessage]
32
32
  def next_event
33
- current = @next
34
- initialize_next_event
35
- current
33
+ @next.tap do
34
+ initialize_next_event
35
+ end
36
36
  end
37
37
 
38
38
  # @return [DomainEventMessage]
@@ -0,0 +1,8 @@
1
+ require 'synapse/event_store/mongo/cursor_event_stream'
2
+ require 'synapse/event_store/mongo/event_store'
3
+
4
+ require 'synapse/event_store/mongo/storage_strategy'
5
+ require 'synapse/event_store/mongo/per_commit_strategy'
6
+ require 'synapse/event_store/mongo/per_event_strategy'
7
+
8
+ require 'synapse/event_store/mongo/template'
@@ -0,0 +1,11 @@
1
+ module Synapse
2
+ module EventStore
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :InMemoryEventStore, 'synapse/event_store/in_memory'
6
+ autoload :Mongo
7
+ end
8
+ end
9
+
10
+ require 'synapse/event_store/errors'
11
+ require 'synapse/event_store/event_store'
@@ -0,0 +1,50 @@
1
+ module Synapse
2
+ module Partitioning
3
+ module AMQP
4
+ # Implementation of a queue reader that subscribes to an AMQP queue
5
+ class AMQPQueueReader < QueueReader
6
+ # The behavior when a message is not acknowledged by a message handler
7
+ #
8
+ # When a message is explicitly rejected, this usually indicates that there was an
9
+ # error while processing the message. When the message is rejected, it can either be
10
+ # put back on the queue so that it can be retried later, or it can be routed as a dead
11
+ # letter if using RabbitMQ.
12
+ #
13
+ # @see http://www.rabbitmq.com/dlx.html
14
+ # @return [Boolean] Default value is true
15
+ attr_accessor :requeue_on_nack
16
+
17
+ # @param [AMQP::Queue] queue
18
+ # @param [AMQP::Channel] channel
19
+ # @param [MessageUnpacker] unpacker
20
+ # @return [undefined]
21
+ def initialize(queue, channel, unpacker)
22
+ @queue = queue
23
+ @channel = channel
24
+ @requeue_on_nack = true
25
+ end
26
+
27
+ # @yield [MessageReceipt] Receipt of the message taken off the queue
28
+ # @return [undefined]
29
+ def subscribe(&handler)
30
+ @queue.subscribe do |headers, packed|
31
+ receipt = MessageReceipt.new headers.delivery_tag, packed, @queue.name
32
+ handler.call receipt
33
+ end
34
+ end
35
+
36
+ # @param [MessageReceipt] receipt
37
+ # @return [undefined]
38
+ def ack_message(receipt)
39
+ @channel.acknowledge receipt.tag
40
+ end
41
+
42
+ # @param [MessageReceipt] receipt
43
+ # @return [undefined]
44
+ def nack_message(receipt)
45
+ @channel.reject receipt.tag, @requeue_on_nack
46
+ end
47
+ end # AMQPQueueReader
48
+ end # AMQP
49
+ end # Partitioning
50
+ end # Synapse
@@ -0,0 +1,31 @@
1
+ module Synapse
2
+ module Partitioning
3
+ module AMQP
4
+ # Implementation of a queue writer that publishes packed messages to an AMQP exchange
5
+ class AMQPQueueWriter < QueueWriter
6
+ # @return [Hash] Additional options that will be used when publishing messages
7
+ attr_accessor :publish_options
8
+
9
+ # @param [AMQP::Exchange] exchange
10
+ # @param [RoutingKeyResolver] key_resolver
11
+ # @return [undefined]
12
+ def initialize(exchange, key_resolver)
13
+ @exchange = exchange
14
+ @key_resolver = key_resolver
15
+ @publish_options = Hash.new
16
+ end
17
+
18
+ # @param [Object] packed
19
+ # @param [Message] unpacked
20
+ # @return [undefined]
21
+ def put_message(packed, unpacked)
22
+ publish_options = {
23
+ routing_key: @key_resolver.resolve_key(unpacked)
24
+ }
25
+
26
+ @exchange.publish(packed, @publish_options.merge(publish_options))
27
+ end
28
+ end # AMQPQueueWriter
29
+ end # AMQP
30
+ end # Partitioning
31
+ end # Synapse
@@ -0,0 +1,26 @@
1
+ module Synapse
2
+ module Partitioning
3
+ module AMQP
4
+ # Represents a mechanism for determining the routing key to use when publishing a message
5
+ class RoutingKeyResolver
6
+ # Returns the routing key to use when publishing the given message
7
+ #
8
+ # @param [Message] message
9
+ # @return [String]
10
+ def resolve_key(message); end
11
+ end
12
+
13
+ # Implementation of a routing key resolver that uses the message payload's module name
14
+ class ModuleRoutingKeyResolver
15
+ # @param [Message] message
16
+ # @return [String]
17
+ def resolve_key(message)
18
+ type = message.payload_type.to_s
19
+ type.deconstantize.underscore.tap do |key|
20
+ key.tr! '/', '.'
21
+ end
22
+ end
23
+ end
24
+ end # AMQP
25
+ end # Partitioning
26
+ end # Synapse
@@ -0,0 +1,3 @@
1
+ require 'synapse/partitioning/amqp/amqp_queue_reader'
2
+ require 'synapse/partitioning/amqp/amqp_queue_writer'
3
+ require 'synapse/partitioning/amqp/key_resolver'
@@ -0,0 +1,31 @@
1
+ module Synapse
2
+ module Partitioning
3
+ # Queue reader that dequeues messages from an in-memory Ruby queue
4
+ class MemoryQueueReader < QueueReader
5
+ # @param [Queue] queue
6
+ # @param [String] name Name of the queue being read from
7
+ # @return [undefined]
8
+ def initialize(queue, name)
9
+ @queue = queue
10
+ @name = name
11
+ end
12
+
13
+ # @yield [MessageReceipt] Receipt of the message taken off the queue
14
+ # @return [undefined]
15
+ def subscribe(&handler)
16
+ loop do
17
+ packed = @queue.pop
18
+
19
+ receipt = MessageReceipt.new 0, packed, @name
20
+ handler.call receipt
21
+ end
22
+ end
23
+
24
+ # @param [MessageReceipt] receipt
25
+ # @return [undefined]
26
+ def nack_message(receipt)
27
+ @queue.push receipt.packed
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module Synapse
2
+ module Partitioning
3
+ # Queue writer that pushes message into an in-memory Ruby queue
4
+ class MemoryQueueWriter < QueueWriter
5
+ # @param [Queue] queue
6
+ # @return [undefined]
7
+ def initialize(queue)
8
+ @queue = queue
9
+ end
10
+
11
+ # @param [Object] packed
12
+ # @param [Message] unpacked
13
+ # @return [undefined]
14
+ def put_message(packed, unpacked)
15
+ @queue.push packed
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ module Synapse
2
+ module Partitioning
3
+ # Receipt used to track messages taken off of a queue
4
+ class MessageReceipt
5
+ # @return [Object] The transport mechanism's record of the message
6
+ attr_reader :tag
7
+
8
+ # @return [Object] The packed message from the transport
9
+ attr_reader :packed
10
+
11
+ # @return [String] The name of the queue the message was read from
12
+ attr_reader :queue_name
13
+
14
+ # @param [Object] tag
15
+ # @param [Object] packed
16
+ # @param [String] queue_name
17
+ # @return [undefined]
18
+ def initialize(tag, packed, queue_name)
19
+ @tag = tag
20
+ @packed = packed
21
+ @queue_name = queue_name
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,93 @@
1
+ module Synapse
2
+ module Partitioning
3
+ # Implementation of a message packer that serializes the metadata and payload of any
4
+ # message and then serializes the entire message so it can go onto the wire.
5
+ class JsonMessagePacker < MessagePacker
6
+ # @param [Serializer] serializer
7
+ # @return [undefined]
8
+ def initialize(serializer)
9
+ @serializer = serializer
10
+
11
+ @serialization_target = String
12
+ # Ideally, we want to serialize the metadata and payload to hashes so that we don't
13
+ # duplicate serialization while serializing the message as a whole to a string
14
+ if serializer.can_serialize_to? Hash
15
+ @serialization_target = Hash
16
+ end
17
+ end
18
+
19
+ # @param [Message] unpacked
20
+ # @return [String]
21
+ def pack_message(unpacked)
22
+ message_type = type_for unpacked
23
+
24
+ metadata = @serializer.serialize unpacked.metadata, @serialization_target
25
+ payload = @serializer.serialize unpacked.payload, @serialization_target
26
+
27
+ packed = {
28
+ message_type: message_type,
29
+ id: unpacked.id,
30
+ metadata: metadata.content,
31
+ payload: payload.content,
32
+ payload_type: payload.type.name,
33
+ payload_revision: payload.type.revision
34
+ }
35
+
36
+ if [:event, :domain_event].include? message_type
37
+ pack_event unpacked, packed
38
+ end
39
+
40
+ if :domain_event == message_type
41
+ pack_domain_event unpacked, packed
42
+ end
43
+
44
+ JSON.dump packed
45
+ end
46
+
47
+ private
48
+
49
+ # Packs additional attributes specific to event messages
50
+ #
51
+ # @param [EventMessage] unpacked
52
+ # @param [Hash] packed
53
+ # @return [undefined]
54
+ def pack_event(unpacked, packed)
55
+ additional = {
56
+ timestamp: unpacked.timestamp.to_i
57
+ }
58
+ packed.merge! additional
59
+ end
60
+
61
+ # Packs additional attributes specific to domain event messages
62
+ #
63
+ # @param [DomainEventMessage] unpacked
64
+ # @param [Hash] packed
65
+ # @return [undefined]
66
+ def pack_domain_event(unpacked, packed)
67
+ additional = {
68
+ aggregate_id: unpacked.aggregate_id.to_s,
69
+ sequence_number: unpacked.sequence_number
70
+ }
71
+ packed.merge! additional
72
+ end
73
+
74
+ # Returns the packed type for the given message
75
+ #
76
+ # @raise [ArgumentError] If the given message isn't supported by this packer
77
+ # @param [Message] unpacked
78
+ # @return [Symbol]
79
+ def type_for(unpacked)
80
+ case unpacked
81
+ when Command::CommandMessage
82
+ :command
83
+ when Domain::DomainEventMessage
84
+ :domain_event
85
+ when Domain::EventMessage
86
+ :event
87
+ else
88
+ raise ArgumentError, 'Unknown message type'
89
+ end
90
+ end
91
+ end # JsonMessagePacker
92
+ end # Partitioning
93
+ end # Synapse