synapse-core 0.5.5 → 0.5.6

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 (54) hide show
  1. data/lib/synapse/auditing/audit_logger.rb +8 -4
  2. data/lib/synapse/auditing/correlation_data_provider.rb +4 -1
  3. data/lib/synapse/auditing/data_provider.rb +3 -1
  4. data/lib/synapse/command/command_bus.rb +14 -6
  5. data/lib/synapse/command/command_filter.rb +5 -3
  6. data/lib/synapse/command/command_handler.rb +5 -3
  7. data/lib/synapse/command/dispatch_interceptor.rb +5 -3
  8. data/lib/synapse/command/duplication.rb +3 -3
  9. data/lib/synapse/command/mapping.rb +1 -1
  10. data/lib/synapse/command/rollback_policy.rb +6 -4
  11. data/lib/synapse/domain/simple_stream.rb +2 -0
  12. data/lib/synapse/domain/stream.rb +10 -6
  13. data/lib/synapse/event_bus/clustering/cluster.rb +10 -0
  14. data/lib/synapse/event_bus/clustering/event_bus.rb +55 -0
  15. data/lib/synapse/event_bus/clustering/selector.rb +14 -0
  16. data/lib/synapse/event_bus/event_bus.rb +9 -3
  17. data/lib/synapse/event_bus/event_listener.rb +5 -3
  18. data/lib/synapse/event_bus/mapping.rb +7 -4
  19. data/lib/synapse/event_sourcing/aggregate_factory.rb +6 -2
  20. data/lib/synapse/event_sourcing/conflict_resolver.rb +11 -0
  21. data/lib/synapse/event_sourcing/member.rb +1 -1
  22. data/lib/synapse/event_sourcing/snapshot/policy.rb +3 -1
  23. data/lib/synapse/event_sourcing/snapshot/taker.rb +3 -1
  24. data/lib/synapse/event_store/event_store.rb +12 -6
  25. data/lib/synapse/event_store/in_memory.rb +2 -2
  26. data/lib/synapse/mapping/mapping.rb +8 -2
  27. data/lib/synapse/process_manager/correlation.rb +2 -2
  28. data/lib/synapse/process_manager/correlation_resolver.rb +5 -3
  29. data/lib/synapse/process_manager/mapping/process.rb +4 -5
  30. data/lib/synapse/process_manager/pessimistic_lock_manager.rb +2 -2
  31. data/lib/synapse/process_manager/process.rb +3 -1
  32. data/lib/synapse/process_manager/process_factory.rb +6 -2
  33. data/lib/synapse/process_manager/process_manager.rb +6 -2
  34. data/lib/synapse/process_manager/process_repository.rb +14 -6
  35. data/lib/synapse/repository/lock_manager.rb +17 -3
  36. data/lib/synapse/repository/locking.rb +3 -1
  37. data/lib/synapse/repository/repository.rb +15 -5
  38. data/lib/synapse/serialization/converter.rb +3 -1
  39. data/lib/synapse/serialization/message/serialization_aware.rb +6 -2
  40. data/lib/synapse/serialization/revision_resolver.rb +3 -1
  41. data/lib/synapse/serialization/serializer.rb +9 -3
  42. data/lib/synapse/uow/nesting.rb +18 -6
  43. data/lib/synapse/uow/transaction_manager.rb +11 -5
  44. data/lib/synapse/upcasting/single_upcaster.rb +15 -16
  45. data/lib/synapse/upcasting/upcaster.rb +20 -17
  46. data/lib/synapse/upcasting/upcaster_chain.rb +2 -2
  47. data/lib/synapse/version.rb +1 -1
  48. data/test/auditing/data_provider_test.rb +9 -1
  49. data/test/command/mapping_test.rb +8 -2
  50. data/test/event_bus/mapping_test.rb +7 -2
  51. data/test/event_sourcing/repository_test.rb +1 -1
  52. data/test/repository/locking_test.rb +3 -0
  53. data/test/upcasting/fixtures.rb +3 -8
  54. metadata +5 -2
@@ -10,7 +10,9 @@ module Synapse
10
10
  # @param [Object] return_value
11
11
  # @param [Array<EventMessage>] events
12
12
  # @return [undefined]
13
- def on_success(command, return_value, events); end
13
+ def on_success(command, return_value, events)
14
+ raise NotImplementedError
15
+ end
14
16
 
15
17
  # Called when a command execution results in an exception being raised
16
18
  #
@@ -22,7 +24,9 @@ module Synapse
22
24
  # @param [Exception] exception
23
25
  # @param [Array<EventMessage>] events
24
26
  # @return [undefined]
25
- def on_failure(command, exception, events); end
26
- end
27
- end
27
+ def on_failure(command, exception, events)
28
+ raise NotImplementedError
29
+ end
30
+ end # AuditLogger
31
+ end # Auditing
28
32
  end
@@ -3,9 +3,12 @@ module Synapse
3
3
  # Implementation of an audit provider that attaches a command's identifier to each event
4
4
  # produced as a result of the execution of that command
5
5
  class CorrelationDataProvider < AuditDataProvider
6
+ # Key that will be used by default
7
+ DEFAULT_CORRELATION_KEY = :command_id
8
+
6
9
  # @param [Symbol] correlation_key
7
10
  # @return [undefined]
8
- def initialize(correlation_key)
11
+ def initialize(correlation_key = DEFAULT_CORRELATION_KEY)
9
12
  @correlation_key = correlation_key
10
13
  end
11
14
 
@@ -8,7 +8,9 @@ module Synapse
8
8
  # @abstract
9
9
  # @param [CommandMessage] command
10
10
  # @return [Hash]
11
- def provide_data_for(command); end
11
+ def provide_data_for(command)
12
+ raise NotImplementedError
13
+ end
12
14
  end # AuditDataProvider
13
15
  end # Auditing
14
16
  end
@@ -14,7 +14,9 @@ module Synapse
14
14
  # @abstract
15
15
  # @param [CommandMessage] command
16
16
  # @return [undefined]
17
- def dispatch(command); end
17
+ def dispatch(command)
18
+ raise NotImplementedError
19
+ end
18
20
 
19
21
  # Dispatches the given command to the handler subscribed to its type and notifies the
20
22
  # given callback of the outcome of the dispatch
@@ -23,7 +25,9 @@ module Synapse
23
25
  # @param [CommandMessage] command
24
26
  # @param [CommandCallback] callback
25
27
  # @return [undefined]
26
- def dispatch_with_callback(command, callback); end
28
+ def dispatch_with_callback(command, callback)
29
+ raise NotImplementedError
30
+ end
27
31
 
28
32
  # Subscribes the given handler to the given command type, replacing the currently subscribed
29
33
  # handler, if any.
@@ -31,7 +35,9 @@ module Synapse
31
35
  # @param [Class] command_type
32
36
  # @param [CommandHandler] handler
33
37
  # @return [undefined]
34
- def subscribe(command_type, handler); end
38
+ def subscribe(command_type, handler)
39
+ raise NotImplementedError
40
+ end
35
41
 
36
42
  # Unsubscribes the given handler from the given command type, if it is currently subscribed
37
43
  # to the given command type.
@@ -39,7 +45,9 @@ module Synapse
39
45
  # @param [Class] command_type
40
46
  # @param [CommandHandler] handler
41
47
  # @return [undefined]
42
- def unsubscribe(command_type, handler); end
43
- end
44
- end
48
+ def unsubscribe(command_type, handler)
49
+ raise NotImplementedError
50
+ end
51
+ end # CommandBus
52
+ end # Command
45
53
  end
@@ -11,7 +11,9 @@ module Synapse
11
11
  # @abstract
12
12
  # @param [CommandMessage] command
13
13
  # @return [CommandMessage] The command to dispatch on the bus
14
- def filter(command); end
15
- end
16
- end
14
+ def filter(command)
15
+ raise NotImplementedError
16
+ end
17
+ end # CommandFilter
18
+ end # Command
17
19
  end
@@ -9,7 +9,9 @@ module Synapse
9
9
  # @param [CommandMessage] command
10
10
  # @param [UnitOfWork] current_unit Current unit of work
11
11
  # @return [Object] The result of handling the given command
12
- def handle(command, current_unit); end
13
- end
14
- end
12
+ def handle(command, current_unit)
13
+ raise NotImplementedError
14
+ end
15
+ end # CommandHandler
16
+ end # Command
15
17
  end
@@ -10,7 +10,9 @@ module Synapse
10
10
  # @param [UnitOfWork] unit The current unit of work for this command dispatch
11
11
  # @param [InterceptorChain] chain
12
12
  # @return [Object] The result of the execution of the command
13
- def intercept(command, unit, chain); end
14
- end
15
- end
13
+ def intercept(command, unit, chain)
14
+ raise NotImplementedError
15
+ end
16
+ end # DispatchInterceptor
17
+ end # Command
16
18
  end
@@ -14,7 +14,7 @@ module Synapse
14
14
  @recorder.record command
15
15
  command
16
16
  end
17
- end
17
+ end # DuplicationFilter
18
18
 
19
19
  # Interceptor that removes commands from the duplication recorder if their execution results
20
20
  # in a transient error (like concurrency error) being raised. This way, the same command can
@@ -38,6 +38,6 @@ module Synapse
38
38
  raise
39
39
  end
40
40
  end
41
- end
42
- end
41
+ end # DuplicationCleanupInterceptor
42
+ end # Command
43
43
  end
@@ -44,7 +44,7 @@ module Synapse
44
44
  raise ArgumentError, 'Not capable of handling [%s] commands' % command.payload_type
45
45
  end
46
46
 
47
- mapping.invoke self, command.payload
47
+ mapping.invoke self, command.payload, command, current_unit
48
48
  end
49
49
 
50
50
  # Subscribes this handler to the given command bus for any types that have been mapped
@@ -7,8 +7,10 @@ module Synapse
7
7
  #
8
8
  # @param [Exception] exception
9
9
  # @return [Boolean]
10
- def should_rollback(exception); end
11
- end
10
+ def should_rollback(exception)
11
+ raise NotImplementedError
12
+ end
13
+ end # RollbackPolicy
12
14
 
13
15
  # Implementation of a rollback policy that performs a rollback on any exception
14
16
  class RollbackOnAnyExceptionPolicy < RollbackPolicy
@@ -17,6 +19,6 @@ module Synapse
17
19
  def should_rollback(exception)
18
20
  true
19
21
  end
20
- end
21
- end
22
+ end # RollbackOnAnyExceptionPolicy
23
+ end # Command
22
24
  end
@@ -2,6 +2,8 @@ module Synapse
2
2
  module Domain
3
3
  # Implementation of a domain event stream that holds a stream of events in memory
4
4
  class SimpleDomainEventStream < DomainEventStream
5
+ # @param [EventMessage...] events
6
+ # @return [undefined]
5
7
  def initialize(*events)
6
8
  @events = events.flatten
7
9
  @next_index = 0
@@ -21,20 +21,24 @@ module Synapse
21
21
  # @abstract
22
22
  # @return [Boolean]
23
23
  def end?
24
- true
24
+ raise NotImplementedError
25
25
  end
26
26
 
27
27
  # Returns the next event in the stream and moves the stream's pointer forward
28
28
  #
29
29
  # @abstract
30
30
  # @return [DomainEventMessage]
31
- def next_event; end
31
+ def next_event
32
+ raise NotImplementedError
33
+ end
32
34
 
33
35
  # Returns the next event in the stream without moving the stream's pointer forward
34
36
  #
35
37
  # @abstract
36
38
  # @return [DomainEventMessage]
37
- def peek; end
39
+ def peek
40
+ raise NotImplementedError
41
+ end
38
42
 
39
43
  # Yields the next domain events in the stream until the end of the stream has been reached
40
44
  #
@@ -59,10 +63,10 @@ module Synapse
59
63
 
60
64
  protected
61
65
 
66
+ # @raise [EndOfStreamError] If at the end of the stream
67
+ # @return [undefined]
62
68
  def assert_valid
63
- if end?
64
- raise EndOfStreamError
65
- end
69
+ raise EndOfStreamError if end?
66
70
  end
67
71
  end # DomainEventStream
68
72
  end # Domain
@@ -0,0 +1,10 @@
1
+ module Synapse
2
+ module EventBus
3
+ # Represents a group of event listeners
4
+ #
5
+ # Clusters allow attributes and behaviors to be applied across an entire group of listeners,
6
+ # such as asynchronous processing, event replay, transaction management and distribution.
7
+ class Cluster
8
+ end # Cluster
9
+ end # EventBus
10
+ end
@@ -0,0 +1,55 @@
1
+ module Synapse
2
+ module EventBus
3
+ class ClusteringEventBus
4
+ # @param [ClusterSelector] cluster_selector
5
+ # @return [undefined]
6
+ def initialize(cluster_selector)
7
+ @cluster_selector = cluster_selector
8
+ @clusters = Set.new
9
+ end
10
+
11
+ # @api public
12
+ # @param [EventMessage...] events
13
+ # @return [undefined]
14
+ def publish(*events)
15
+ events.flatten!
16
+
17
+ @clusters.each do |cluster|
18
+ cluster.publish events
19
+ end
20
+ end
21
+
22
+ # @api public
23
+ # @raise [SubscriptionFailedError] If subscription of an event listener failed
24
+ # @param [EventListener] listener
25
+ # @return [undefined]
26
+ def subscribe(listener)
27
+ select_cluster(listener).subscribe(listener)
28
+ end
29
+
30
+ # @api public
31
+ # @param [EventListener] listener
32
+ # @return [undefined]
33
+ def unsubscribe(listener)
34
+ select_cluster(listener).unsubscribe(listener)
35
+ end
36
+
37
+ private
38
+
39
+ # @raise [SubscriptionFailedError] If no suitable cluster for listener
40
+ # @param [EventListener] listener
41
+ # @return [Cluster]
42
+ def select_cluster(listener)
43
+ cluster = @cluster_selector.select_cluster listener
44
+
45
+ unless cluster
46
+ raise SubscriptionFailedError, 'Unable to find suitable cluster for [%s]' % listener.class
47
+ end
48
+
49
+ @clusters.add cluster
50
+
51
+ cluster
52
+ end
53
+ end # ClusteringEventBus
54
+ end # EventBus
55
+ end
@@ -0,0 +1,14 @@
1
+ module Synapse
2
+ module EventBus
3
+ # Represents a mechanism for assigning event listeners to clusters
4
+ # @abstract
5
+ class ClusterSelector
6
+ # Selects and returns a suitable cluster for the given event listener
7
+ #
8
+ # @abstract
9
+ # @param [EventListener] listener
10
+ # @return [Cluster] Returns nil if no suitable cluster
11
+ def select_cluster(listener); end
12
+ end # ClusterSelector
13
+ end # EventBus
14
+ end
@@ -15,7 +15,9 @@ module Synapse
15
15
  # @abstract
16
16
  # @param [EventMessage...] events
17
17
  # @return [undefined]
18
- def publish(*events); end
18
+ def publish(*events)
19
+ raise NotImplementedError
20
+ end
19
21
 
20
22
  # Subscribes the given listener to this event bus
21
23
  #
@@ -23,14 +25,18 @@ module Synapse
23
25
  # @raise [SubscriptionFailedError] If subscription of an event listener failed
24
26
  # @param [EventListener] listener
25
27
  # @return [undefined]
26
- def subscribe(listener); end
28
+ def subscribe(listener)
29
+ raise NotImplementedError
30
+ end
27
31
 
28
32
  # Unsubscribes the given listener from this event bus
29
33
  #
30
34
  # @abstract
31
35
  # @param [EventListener] listener
32
36
  # @return [undefined]
33
- def unsubscribe(listener); end
37
+ def unsubscribe(listener)
38
+ raise NotImplementedError
39
+ end
34
40
  end
35
41
 
36
42
  # Raised when the subscription of an event listener has not succeeded. Generally, this means that
@@ -12,7 +12,9 @@ module Synapse
12
12
  # @abstract
13
13
  # @param [EventMessage] event
14
14
  # @return [undefined]
15
- def notify(event); end
16
- end
17
- end
15
+ def notify(event)
16
+ raise NotImplementedError
17
+ end
18
+ end # EventListener
19
+ end # EventBus
18
20
  end
@@ -10,6 +10,10 @@ module Synapse
10
10
  # # ...
11
11
  # end
12
12
  #
13
+ # map_event UserProfileUpdated do |event, message|
14
+ # # ...
15
+ # end
16
+ #
13
17
  # map_event UserBanned, :to => :on_banned
14
18
  # end
15
19
  module MappingEventListener
@@ -37,10 +41,9 @@ module Synapse
37
41
  # @return [undefined]
38
42
  def notify(event)
39
43
  mapping = event_mapper.mapping_for event.payload_type
40
-
41
- return unless mapping
42
-
43
- mapping.invoke self, event.payload
44
+ if mapping
45
+ mapping.invoke self, event.payload, event
46
+ end
44
47
  end
45
48
  end # MappingEventListener
46
49
  end # EventBus
@@ -16,11 +16,15 @@ module Synapse
16
16
 
17
17
  # @abstract
18
18
  # @return [Class] Type of aggregate being created by this factory
19
- def aggregate_type; end
19
+ def aggregate_type
20
+ raise NotImplementedError
21
+ end
20
22
 
21
23
  # @abstract
22
24
  # @return [String] Type identifier used to store the aggregate in the event store
23
- def type_identifier; end
25
+ def type_identifier
26
+ raise NotImplementedError
27
+ end
24
28
  end # AggregateFactory
25
29
 
26
30
  # Aggregate factory that uses a convention to create instances of aggregates
@@ -10,6 +10,17 @@ module Synapse
10
10
  # an exception. Otherwise, the changes will be applied.
11
11
  #
12
12
  # @abstract
13
+ # @raise [ConflictingModificationException] If any conflicts were detected
14
+ # @param [Array] applied_changes List of changes applied to the aggregate
15
+ # @param [Array] committed_changes List of events that were unexpected by the command handler
16
+ # @return [undefined]
17
+ def resolve_conflicts(applied_changes, committed_changes)
18
+ raise NotImplementedError
19
+ end
20
+ end
21
+
22
+ # Conflict resolver that accepts any unseen changes to an aggregate
23
+ class AcceptAllConflictResolver < ConflictResolver
13
24
  # @raise [ConflictingModificationException] If any conflicts were detected
14
25
  # @param [Array] applied_changes List of changes applied to the aggregate
15
26
  # @param [Array] committed_changes List of events that were unexpected by the command handler
@@ -77,7 +77,7 @@ module Synapse
77
77
  def handle_event(event)
78
78
  mapping = self.event_mapper.mapping_for event.payload_type
79
79
  if mapping
80
- mapping.invoke self, event.payload
80
+ mapping.invoke self, event.payload, event
81
81
  end
82
82
  end
83
83
 
@@ -6,7 +6,9 @@ module Synapse
6
6
  #
7
7
  # @param [AggregateRoot] aggregate
8
8
  # @return [Boolean]
9
- def should_snapshot?(aggregate); end
9
+ def should_snapshot?(aggregate)
10
+ raise NotImplementedError
11
+ end
10
12
  end # SnapshotPolicy
11
13
 
12
14
  # Snapshot policy that takes a snapshot if the number of events committed in an aggregate since
@@ -43,7 +43,9 @@ module Synapse
43
43
  # @param [Object] aggregate_id
44
44
  # @param [DomainEventStream] stream
45
45
  # @return [DomainEventMessage]
46
- def create_snapshot(type_identifier, aggregate_id, stream); end
46
+ def create_snapshot(type_identifier, aggregate_id, stream)
47
+ raise NotImplementedError
48
+ end
47
49
  end # SnapshotTaker
48
50
  end # EventSourcing
49
51
  end
@@ -15,7 +15,9 @@ module Synapse
15
15
  # @param [String] type_identifier Type descriptor of the aggregate to retrieve
16
16
  # @param [Object] aggregate_id
17
17
  # @return [DomainEventStream]
18
- def read_events(type_identifier, aggregate_id); end
18
+ def read_events(type_identifier, aggregate_id)
19
+ raise NotImplementedError
20
+ end
19
21
 
20
22
  # Appends the domain events in the given stream to the event store
21
23
  #
@@ -24,8 +26,10 @@ module Synapse
24
26
  # @param [String] type_identifier Type descriptor of the aggregate to append to
25
27
  # @param [DomainEventStream] stream
26
28
  # @return [undefined]
27
- def append_events(type_identifier, stream); end
28
- end
29
+ def append_events(type_identifier, stream)
30
+ raise NotImplementedError
31
+ end
32
+ end # EventStore
29
33
 
30
34
  # Represents an event store with the capability to manage aggregate snapshots
31
35
  # @abstract
@@ -37,7 +41,9 @@ module Synapse
37
41
  # @param [String] type_identifier Type descriptor of the aggregate to append to
38
42
  # @param [DomainEventMessage] snapshot_event
39
43
  # @return [undefined]
40
- def append_snapshot_event(type_identifier, snapshot_event); end
41
- end
42
- end
44
+ def append_snapshot_event(type_identifier, snapshot_event)
45
+ raise NotImplementedError
46
+ end
47
+ end # SnapshotEventStore
48
+ end # EventStore
43
49
  end
@@ -54,6 +54,6 @@ module Synapse
54
54
 
55
55
  @streams.store aggregate_id, Array.new
56
56
  end
57
- end
58
- end
57
+ end # InMemoryEventStore
58
+ end # EventStore
59
59
  end
@@ -29,9 +29,15 @@ module Synapse
29
29
  # @return [Object] The result of the handler invocation
30
30
  def invoke(target, *args)
31
31
  if @handler.is_a? Symbol
32
- target.send(@handler, *args)
32
+ method = target.method @handler
33
+
34
+ if method.arity > args.size || method.arity == 0
35
+ raise ArgumentError, 'Method signature is invalid'
36
+ end
37
+
38
+ method.call(*args.slice(0, method.arity))
33
39
  else
34
- target.instance_exec(*args, &@handler)
40
+ target.instance_exec *args, &@handler
35
41
  end
36
42
  end
37
43
 
@@ -27,6 +27,6 @@ module Synapse
27
27
  def hash
28
28
  @key.hash ^ @value.hash
29
29
  end
30
- end
31
- end
30
+ end # Correlation
31
+ end # ProcessManager
32
32
  end
@@ -8,7 +8,9 @@ module Synapse
8
8
  # @abstract
9
9
  # @param [EventMessage] event
10
10
  # @return [Correlation]
11
- def resolve(event); end
12
- end
13
- end
11
+ def resolve(event)
12
+ raise NotImplementedError
13
+ end
14
+ end # CorrelationResolver
15
+ end # ProcessManager
14
16
  end
@@ -33,11 +33,10 @@ module Synapse
33
33
  return unless @active
34
34
 
35
35
  mapping = event_mapper.mapping_for event.payload_type
36
-
37
- return unless mapping
38
-
39
- mapping.invoke self, event.payload
40
- finish if mapping.options[:finish]
36
+ if mapping
37
+ mapping.invoke self, event.payload, event
38
+ finish if mapping.options[:finish]
39
+ end
41
40
  end
42
41
  end # MappingProcess
43
42
  end # ProcessManager
@@ -18,6 +18,6 @@ module Synapse
18
18
  def release_lock(process_id)
19
19
  @lock.release_lock process_id
20
20
  end
21
- end
22
- end
21
+ end # PessimisticLockManager
22
+ end # ProcessManager
23
23
  end
@@ -43,7 +43,9 @@ module Synapse
43
43
  # @abstract
44
44
  # @param [EventMessage] event
45
45
  # @return [undefined]
46
- def handle(event); end
46
+ def handle(event)
47
+ raise NotImplementedError
48
+ end
47
49
 
48
50
  protected
49
51
 
@@ -11,14 +11,18 @@ module Synapse
11
11
  # @abstract
12
12
  # @param [Class] process_type
13
13
  # @return [Process]
14
- def create(process_type); end
14
+ def create(process_type)
15
+ raise NotImplementedError
16
+ end
15
17
 
16
18
  # Returns true if processes of the given type can be created by this factory
17
19
  #
18
20
  # @abstract
19
21
  # @param [Class] process_type
20
22
  # @return [Boolean]
21
- def supports(process_type); end
23
+ def supports(process_type)
24
+ raise NotImplementedError
25
+ end
22
26
  end # ProcessFactory
23
27
 
24
28
  # Generic implementation of a process factory that supports any process implementations that
@@ -52,13 +52,17 @@ module Synapse
52
52
  # @param [Class] process_type
53
53
  # @param [EventMessage] event
54
54
  # @return [Symbol]
55
- def creation_policy_for(process_type, event); end
55
+ def creation_policy_for(process_type, event)
56
+ raise NotImplementedError
57
+ end
56
58
 
57
59
  # @abstract
58
60
  # @param [Class] process_type
59
61
  # @param [EventMessage] event
60
62
  # @return [Correlation] Returns nil if no correlation could be extracted
61
- def extract_correlation(process_type, event); end
63
+ def extract_correlation(process_type, event)
64
+ raise NotImplementedError
65
+ end
62
66
 
63
67
  # Determines whether or not a new process should be started, based off of existing processes
64
68
  # and the creation policy for the event and process