evil_events 0.1.0rc1

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 (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +84 -0
  5. data/.travis.yml +10 -0
  6. data/.yardopts +1 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Gemfile +6 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +17 -0
  11. data/Rakefile +6 -0
  12. data/bin/console +12 -0
  13. data/bin/setup +8 -0
  14. data/evil_events.gemspec +42 -0
  15. data/lib/evil_events/boot_point.rb +17 -0
  16. data/lib/evil_events/config.rb +30 -0
  17. data/lib/evil_events/core/activity_logging.rb +24 -0
  18. data/lib/evil_events/core/broadcasting/adapters/memory_async.rb +20 -0
  19. data/lib/evil_events/core/broadcasting/adapters/memory_sync.rb +20 -0
  20. data/lib/evil_events/core/broadcasting/adapters.rb +11 -0
  21. data/lib/evil_events/core/broadcasting/dispatcher/dispatchable.rb +17 -0
  22. data/lib/evil_events/core/broadcasting/dispatcher.rb +17 -0
  23. data/lib/evil_events/core/broadcasting/emitter.rb +45 -0
  24. data/lib/evil_events/core/broadcasting.rb +13 -0
  25. data/lib/evil_events/core/events/abstract_event.rb +44 -0
  26. data/lib/evil_events/core/events/event_class_factory.rb +54 -0
  27. data/lib/evil_events/core/events/event_extensions/adapter_customizable.rb +49 -0
  28. data/lib/evil_events/core/events/event_extensions/manageable.rb +26 -0
  29. data/lib/evil_events/core/events/event_extensions/observable.rb +49 -0
  30. data/lib/evil_events/core/events/event_extensions/payloadable/abstract_payload.rb +24 -0
  31. data/lib/evil_events/core/events/event_extensions/payloadable.rb +52 -0
  32. data/lib/evil_events/core/events/event_extensions/serializable.rb +21 -0
  33. data/lib/evil_events/core/events/event_extensions/type_aliasing.rb +87 -0
  34. data/lib/evil_events/core/events/manager/subscriber_list.rb +30 -0
  35. data/lib/evil_events/core/events/manager.rb +78 -0
  36. data/lib/evil_events/core/events/manager_factory.rb +17 -0
  37. data/lib/evil_events/core/events/manager_registry.rb +141 -0
  38. data/lib/evil_events/core/events/serializers/hash.rb +51 -0
  39. data/lib/evil_events/core/events/serializers/json.rb +43 -0
  40. data/lib/evil_events/core/events/serializers.rb +16 -0
  41. data/lib/evil_events/core/events/subscriber/mixin.rb +28 -0
  42. data/lib/evil_events/core/events/subscriber.rb +43 -0
  43. data/lib/evil_events/core/events.rb +25 -0
  44. data/lib/evil_events/core.rb +10 -0
  45. data/lib/evil_events/shared/combined_context.rb +113 -0
  46. data/lib/evil_events/shared/combined_context_mixin.rb +43 -0
  47. data/lib/evil_events/shared/configurable.rb +7 -0
  48. data/lib/evil_events/shared/delegator_resolver.rb +36 -0
  49. data/lib/evil_events/shared/dependency_container.rb +7 -0
  50. data/lib/evil_events/shared/logger.rb +13 -0
  51. data/lib/evil_events/shared/mockable_class_builder.rb +27 -0
  52. data/lib/evil_events/shared/structure.rb +7 -0
  53. data/lib/evil_events/shared/types.rb +9 -0
  54. data/lib/evil_events/shared.rb +16 -0
  55. data/lib/evil_events/system/mock.rb +70 -0
  56. data/lib/evil_events/system.rb +149 -0
  57. data/lib/evil_events/version.rb +7 -0
  58. data/lib/evil_events.rb +53 -0
  59. metadata +269 -0
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilEvents::Core::Events::EventExtensions
4
+ # @api private
5
+ # @since 0.1.0
6
+ module AdapterCustomizable
7
+ class << self
8
+ # @param base_class [Class]
9
+ #
10
+ # @since 0.1.0
11
+ def included(base_class)
12
+ base_class.extend(ClassMethods)
13
+ end
14
+ end
15
+
16
+ # @return [EvilEvents::Core::Broadcasting::Dispatcher::Dispatchable]
17
+ #
18
+ # @since 0.1.0
19
+ def adapter
20
+ self.class.adapter
21
+ end
22
+
23
+ # @return [EvilEvents::Core::Broadcasting::Dispatcher::Dispatchable]
24
+ #
25
+ # @since 0.1.0
26
+ def adapter_name
27
+ self.class.adapter_name
28
+ end
29
+
30
+ # @since 0.1.0
31
+ module ClassMethods
32
+ # @param identifier [Symbol, String]
33
+ # @return [EvilEvents::Core::Broadcasting::Dispatcher::Dispatchable]
34
+ #
35
+ # @since 0.1.0
36
+ def adapter(identifier = nil)
37
+ @adapter_identifier = identifier if identifier
38
+ EvilEvents::BootPoint::System[:event_system].resolve_adapter(adapter_name)
39
+ end
40
+
41
+ # @return [Symbol, String]
42
+ #
43
+ # @since 0.1.0
44
+ def adapter_name
45
+ @adapter_identifier || EvilEvents::BootPoint::System[:config].adapter.default
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilEvents::Core::Events::EventExtensions
4
+ # @api private
5
+ # @since 0.1.0
6
+ module Manageable
7
+ class << self
8
+ # @param base_class [Class]
9
+ #
10
+ # @since 0.1.0
11
+ def included(base_class)
12
+ base_class.extend(ClassMethods)
13
+ end
14
+ end
15
+
16
+ # @since 0.1.0
17
+ module ClassMethods
18
+ # @return void
19
+ #
20
+ # @since 0.1.0
21
+ def manage!
22
+ EvilEvents::BootPoint::System[:event_system].register_event_class(self)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilEvents::Core::Events::EventExtensions
4
+ # @api private
5
+ # @since 0.1.0
6
+ module Observable
7
+ class << self
8
+ # @param base_class [Class]
9
+ #
10
+ # @since 0.1.0
11
+ def included(base_class)
12
+ base_class.extend(ClassMethods)
13
+ end
14
+ end
15
+
16
+ # @return [Array<EvilEvents::Core::Events::Subscriber>]
17
+ #
18
+ # @since 0.1.0
19
+ def observers
20
+ self.class.observers
21
+ end
22
+
23
+ # @since 0.1.0
24
+ module ClassMethods
25
+ # @param raw_subscriber [Object]
26
+ # @param delegator [Symbol, String, NilClass]
27
+ #
28
+ # @since 0.1.0
29
+ def observe(raw_subscriber, delegator: nil)
30
+ EvilEvents::BootPoint::System[:event_system].observe(self, raw_subscriber, delegator)
31
+ end
32
+
33
+ # @param delegator [Symbol, String, NilClass]
34
+ #
35
+ # @since 0.1.0
36
+ def default_delegator(delegator = nil)
37
+ @default_delegator = delegator if delegator
38
+ @default_delegator || EvilEvents::BootPoint::System[:config].subscriber.default_delegator
39
+ end
40
+
41
+ # @return [Array]
42
+ #
43
+ # @since 0.1.0
44
+ def observers
45
+ EvilEvents::BootPoint::System[:event_system].observers(self)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilEvents::Core::Events::EventExtensions::Payloadable
4
+ # @abstract
5
+ # @api private
6
+ # @since 0.1.0
7
+ class AbstractPayload < EvilEvents::Shared::Structure
8
+ class << self
9
+ # @since 0.1.0
10
+ alias_method :_native_attribute, :attribute
11
+
12
+ # @param key [Symbol]
13
+ # @param type [EvilEvents::Shared::Types::Any]
14
+ #
15
+ # @since 0.1.0
16
+ def attribute(key, type = EvilEvents::Types::Any)
17
+ _native_attribute(key, type)
18
+ end
19
+ end
20
+
21
+ # NOTE: dry-struct API + dry-initializer API
22
+ constructor_type :strict_with_defaults
23
+ end
24
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilEvents::Core::Events::EventExtensions
4
+ # @api private
5
+ # @since 0.1.0
6
+ module Payloadable
7
+ class << self
8
+ # @param base_class [Class]
9
+ #
10
+ # @since 0.1.0
11
+ def included(base_class)
12
+ base_class.extend(ClassMethods)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ # @return [AbstractPayload]
19
+ #
20
+ # @since 0.1.0
21
+ def payload_class
22
+ self.class.const_get(:Payload)
23
+ end
24
+
25
+ # @since 0.1.0
26
+ module ClassMethods
27
+ # @param child_class [Class]
28
+ #
29
+ # @since 0.1.0
30
+ def inherited(child_class)
31
+ child_class.const_set(:Payload, Class.new(AbstractPayload))
32
+ super
33
+ end
34
+
35
+ # @param key [Symbol]
36
+ # @param type [EvilEvents::Shared::Types::Any]
37
+ # @return void
38
+ #
39
+ # @since 0.1.0
40
+ def attribute(key, type = EvilEvents::Shared::Types::Any)
41
+ const_get(:Payload).attribute(key, type)
42
+ end
43
+
44
+ # @return [Array<Symbol>]
45
+ #
46
+ # @since 0.1.0
47
+ def attribute_names
48
+ const_get(:Payload).attribute_names
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilEvents::Core::Events::EventExtensions
4
+ # @api private
5
+ # @since 0.1.0
6
+ module Serializable
7
+ # @return [Hash]
8
+ #
9
+ # @since 0.1.0
10
+ def serialize_to_hash
11
+ EvilEvents::Core::Events::Serializers[:hash].serialize(self)
12
+ end
13
+
14
+ # @return [String]
15
+ #
16
+ # @since 0.1.0
17
+ def serialize_to_json
18
+ EvilEvents::Core::Events::Serializers[:json].serialize(self)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilEvents::Core::Events::EventExtensions
4
+ # @api private
5
+ # @since 0.1.0
6
+ module TypeAliasing
7
+ # @since 0.1.0
8
+ TypeAliasingError = Class.new(StandardError)
9
+ # @since 0.1.0
10
+ IncopatibleEventTypeError = Class.new(TypeAliasingError)
11
+ # @since 0.1.0
12
+ EventTypeNotDefinedError = Class.new(TypeAliasingError)
13
+ # @since 0.1.0
14
+ EventTypeAlreadyDefinedError = Class.new(TypeAliasingError)
15
+
16
+ class << self
17
+ # @param base_class [Class]
18
+ #
19
+ # @since 0.1.0
20
+ def included(base_class)
21
+ base_class.extend(ClassMethods)
22
+ end
23
+ end
24
+
25
+ # @return [String]
26
+ #
27
+ # @since 0.1.0
28
+ def type
29
+ self.class.type
30
+ end
31
+
32
+ module ClassMethods
33
+ # @param type_alias [String, NilClass]
34
+ # @return [String]
35
+ #
36
+ # @since 0.1.0
37
+ def type(type_alias = nil)
38
+ case
39
+ when incompatible_type_alias_type?(type_alias)
40
+ raise IncopatibleEventTypeError
41
+ when fetching_type_alias_when_type_alias_not_defined?(type_alias)
42
+ raise EventTypeNotDefinedError
43
+ when providing_type_alias_when_type_alias_already_defined?(type_alias)
44
+ raise EventTypeAlreadyDefinedError
45
+ when tries_to_define_type_alias_first_time?(type_alias)
46
+ @type = type_alias
47
+ end
48
+
49
+ @type
50
+ end
51
+
52
+ private
53
+
54
+ # @param type_alias [String, NilClass]
55
+ # @return [Boolean]
56
+ #
57
+ # @since 0.1.0
58
+ def incompatible_type_alias_type?(type_alias)
59
+ !(type_alias.is_a?(NilClass) || type_alias.is_a?(String))
60
+ end
61
+
62
+ # @param type_alias [String, NilClass]
63
+ # @return [Boolean]
64
+ #
65
+ # @since 0.1.0
66
+ def fetching_type_alias_when_type_alias_not_defined?(type_alias)
67
+ !instance_variable_defined?(:@type) && type_alias.nil?
68
+ end
69
+
70
+ # @param type_alias [String, NilClass]
71
+ # @return [Boolean]
72
+ #
73
+ # @since 0.1.0
74
+ def providing_type_alias_when_type_alias_already_defined?(type_alias)
75
+ instance_variable_defined?(:@type) && type_alias
76
+ end
77
+
78
+ # @param type_alias [String, NilClass]
79
+ # @return [Boolean]
80
+ #
81
+ # @since 0.1.0
82
+ def tries_to_define_type_alias_first_time?(type_alias)
83
+ !instance_variable_defined?(:@type) && type_alias
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ class EvilEvents::Core::Events::Manager
4
+ # @api private
5
+ # @since 0.1.0
6
+ class SubscriberList < Concurrent::Array
7
+ # @param source_subscriber [Object]
8
+ # @return [Boolean]
9
+ #
10
+ # @since 0.1.0
11
+ def registered?(source_subscriber)
12
+ any? { |subscriber| subscriber.source_object == source_subscriber }
13
+ end
14
+
15
+ # @param source_subscriber [Object]
16
+ # @return [EvilEvents::Core::Events::Subscriber]
17
+ #
18
+ # @since 0.1.0
19
+ def wrapper_of(source_subscriber)
20
+ find { |subscriber| subscriber.source_object == source_subscriber }
21
+ end
22
+
23
+ # @return [Array<Object>]
24
+ #
25
+ # @since 0.1.0
26
+ def sources
27
+ map(&:source_object)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilEvents::Core::Events
4
+ # @api private
5
+ # @since 0.1.0
6
+ class Manager
7
+ # @since 0.1.0
8
+ ManagerError = Class.new(StandardError)
9
+ # @since 0.1.0
10
+ InconsistentEventClassError = Class.new(ManagerError)
11
+ # @since 0.1.0
12
+ InvalidDelegatorTypeError = Class.new(ManagerError)
13
+
14
+ # @return [EvilEvents::Core::Events::AbstractEvent]
15
+ #
16
+ # @since 0.1.0
17
+ attr_reader :event_class
18
+
19
+ # @return [Concurrent::Array<EvilEvents::Core::Events::Subscriber>]
20
+ #
21
+ # @since 0.1.0
22
+ attr_reader :subscribers
23
+
24
+ # @param event_class [Class{EvilEvents::Core::Events::AbstractEvent}]
25
+ #
26
+ # @since 0.1.0
27
+ def initialize(event_class)
28
+ @event_class = event_class
29
+ @subscribers = SubscriberList.new
30
+ end
31
+
32
+ # @param raw_subscriber [Object]
33
+ # @param delegator [Symbol, String, NilClass]
34
+ # @raise [InvalidDelegatorTypeError]
35
+ # @return void
36
+ #
37
+ # @since 0.1.0
38
+ def observe(raw_subscriber, delegator = nil)
39
+ case delegator
40
+ when NilClass, Symbol, String # TODO: think about Dry::Types checker
41
+ subscribers.push(create_event_subscriber(raw_subscriber, delegator))
42
+ else
43
+ raise InvalidDelegatorTypeError
44
+ end
45
+ end
46
+
47
+ # @param event [EvilEvents::Core::Events::AbstractEvent]
48
+ # @raise [InconsistentEventClassError]
49
+ # @return void
50
+ #
51
+ # @since 0.1.0
52
+ def notify(event)
53
+ raise InconsistentEventClassError unless event.is_a?(event_class)
54
+ # TODO: separate notification logic to worker/jobs
55
+ subscribers.each { |subscriber| subscriber.notify(event) }
56
+ end
57
+
58
+ # @return [String, Symbol]
59
+ #
60
+ # @since 0.1.0
61
+ def event_type
62
+ event_class.type
63
+ end
64
+
65
+ private
66
+
67
+ # @param raw_subscriber [Object]
68
+ # @param delegator [Symbol, String, NilClass]
69
+ # @return [EvilEvents::Core::Events::Subscriber]
70
+ #
71
+ # @since 0.1.0
72
+ def create_event_subscriber(raw_subscriber, delegator)
73
+ delegation = -> { delegator || event_class.default_delegator }
74
+ resolver = EvilEvents::Shared::DelegatorResolver.new(delegation)
75
+ EvilEvents::Core::Events::Subscriber.new(raw_subscriber, resolver)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilEvents::Core::Events
4
+ # @api private
5
+ # @since 0.1.0
6
+ module ManagerFactory
7
+ class << self
8
+ # @param event_class [Class{EvilEvents::Core::Events::AbstractEvent}]
9
+ # @return [EvilEvents::Core::Events::Manager]
10
+ #
11
+ # @since 0.1.0
12
+ def create(event_class)
13
+ Manager.new(event_class)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilEvents::Core::Events
4
+ # @api private
5
+ # @since 0.1.0
6
+ class ManagerRegistry
7
+ # @since 0.1.0
8
+ extend Forwardable
9
+
10
+ # @since 0.1.0
11
+ ManagerRegistryError = Class.new(StandardError)
12
+ # @since 0.1.0
13
+ IncorrectManagerObjectError = Class.new(ManagerRegistryError)
14
+ # @since 0.1.0
15
+ NonManagedEventClassError = Class.new(ManagerRegistryError)
16
+ # @since 0.1.0
17
+ AlreadyManagedEventClassError = Class.new(ManagerRegistryError)
18
+
19
+ def_delegators :managers, :empty?, :size
20
+
21
+ # @return [Concurrent::Map]
22
+ #
23
+ # @since 0.1.0
24
+ attr_reader :managers
25
+
26
+ # @since 0.1.0
27
+ def initialize
28
+ @managers = Concurrent::Map.new
29
+ end
30
+
31
+ # @param event_class [Class{EvilEvents::Core::Events::AbstractEvent}]
32
+ # @raise [NonManagedEventClassError]
33
+ # @return [EvilEvents::Core::Events::Manager]
34
+ #
35
+ # @since 0.1.0
36
+ def manager_of_event(event_class)
37
+ # NOTE: raise exceptions to simplify runtime problems resolving
38
+ managers[event_class] || (raise NonManagedEventClassError)
39
+ end
40
+
41
+ # @param event_type [String]
42
+ # @return [EvilEvents::Core::Events::Manager]
43
+ # @see manager_of_event
44
+ #
45
+ # @since 0.1.0
46
+ def manager_of_event_type(event_type)
47
+ event_class = managed_events.find { |managed_event| managed_event.type == event_type }
48
+ manager_of_event(event_class)
49
+ end
50
+
51
+ # @param manager [EvilEvents::Core::Events::Manager]
52
+ # @raise [IncorrectManagerObjectError]
53
+ # @raise [AlreadyManagedEventClassError]
54
+ # @return void
55
+ #
56
+ # @since 0.1.0
57
+ def register(manager)
58
+ raise IncorrectManagerObjectError unless manager.is_a?(EvilEvents::Core::Events::Manager)
59
+
60
+ if potential_manager_duplicate?(manager) || !managed_event_type?(manager.event_type)
61
+ managers[manager.event_class] = manager
62
+ else
63
+ raise AlreadyManagedEventClassError
64
+ end
65
+ end
66
+
67
+ # @param event_class [Class{EvilEvents::Core::Events::AbstractEvent}]
68
+ # @return void
69
+ # @see register
70
+ #
71
+ # @since 0.1.0
72
+ def register_with(event_class)
73
+ register(ManagerFactory.create(event_class))
74
+ end
75
+
76
+ # @param manager [EvilEvents::Core::Events::Manager]
77
+ # @return void
78
+ #
79
+ # @since 0.1.0
80
+ def unregister(manager)
81
+ managers.delete_pair(manager.event_class, manager)
82
+ end
83
+
84
+ # @param event_class [Class{EvilEvents::Core::Events::AbstractEvent}]
85
+ # @return void
86
+ #
87
+ # @since 0.1.0
88
+ def unregister_with(event_class)
89
+ managers.delete(event_class)
90
+ end
91
+
92
+ # @param manager [EvilEvents::Core::Events::Manager]
93
+ # @return [Boolean]
94
+ #
95
+ # @since 0.1.0
96
+ def include?(manager)
97
+ managed_event?(manager.event_class) && manager_of_event(manager.event_class) == manager
98
+ end
99
+
100
+ # @param event_class [Class{EvilEvents::Core::Events::AbstractEvent}]
101
+ # @return [Boolean]
102
+ #
103
+ # @since 0.1.0
104
+ def managed_event?(event_class)
105
+ managers.key?(event_class)
106
+ end
107
+
108
+ private
109
+
110
+ # @return [Array<EvilEvents::Core::Events::AbstractEvent>]
111
+ #
112
+ # @since 0.1.0
113
+ def managed_events
114
+ managers.keys
115
+ end
116
+
117
+ # @return [Array<String>]
118
+ #
119
+ # @since 0.1.0
120
+ def managed_event_types
121
+ managed_events.map(&:type)
122
+ end
123
+
124
+ # @param event_type [String]
125
+ # @return [Boolean]
126
+ #
127
+ # @since 0.1.0
128
+ def managed_event_type?(event_type)
129
+ managed_event_types.include?(event_type)
130
+ end
131
+
132
+ # @param manager [EvilEvents::Core::Events::Manager]
133
+ # @return [Boolean]
134
+ #
135
+ # @since 0.1.0
136
+ def potential_manager_duplicate?(manager)
137
+ return false unless managed_event?(manager.event_class)
138
+ manager_of_event(manager.event_class).event_type == manager.event_type
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ class EvilEvents::Core::Events::Serializers
4
+ # @api public
5
+ # @since 0.1.0
6
+ module Hash
7
+ module_function
8
+
9
+ # @param event [EvilEvents::Core::Events::AbstractEvent]
10
+ # @raise [SerializationError]
11
+ # @return [::Hash]
12
+ #
13
+ # @since 0.1.0
14
+ def serialize(event)
15
+ raise SerializationError unless event.is_a?(EvilEvents::Core::Events::AbstractEvent)
16
+
17
+ { type: event.type, payload: event.payload }
18
+ end
19
+
20
+ # @param hash [::Hash]
21
+ # @raise [DeserializationError]
22
+ # @return [EvilEvents::Core::Events::AbstractEvent]
23
+ #
24
+ # @since 0.1.0
25
+ def deserialize(hash)
26
+ raise DeserializationError unless hash.is_a?(::Hash)
27
+ event_type = hash[:type] || hash['type']
28
+ event_payload = hash[:payload] || hash['payload']
29
+ raise DeserializationError unless event_type && event_payload
30
+ raise DeserializationError unless event_payload.is_a?(::Hash)
31
+
32
+ EvilEvents::BootPoint::System[:event_system].resolve_event_object(
33
+ event_type, symbolized_event_payload(event_payload)
34
+ )
35
+ end
36
+
37
+ # @param payload_hash [::Hash]
38
+ # @return [::Hash]
39
+ #
40
+ # @since 0.1.0
41
+ def symbolized_event_payload(payload_hash)
42
+ payload_hash.each_pair.each_with_object({}) do |(key, value), result_hash|
43
+ result_hash[key.to_sym] = value
44
+ end
45
+ end
46
+ private_class_method :symbolized_event_payload
47
+ end
48
+
49
+ # @since 0.1.0
50
+ register(:hash) { Hash }
51
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ class EvilEvents::Core::Events::Serializers
4
+ # @api public
5
+ # @since 0.1.0
6
+ module JSON
7
+ module_function
8
+
9
+ # @param event [EvilEvents::Core::Events::AbstractEvent]
10
+ # @raise [SerializationError]
11
+ # @return [::Hash]
12
+ #
13
+ # @since 0.1.0
14
+ def serialize(event)
15
+ raise SerializationError unless event.is_a?(EvilEvents::Core::Events::AbstractEvent)
16
+
17
+ ::JSON.generate(type: event.type, payload: event.payload)
18
+ end
19
+
20
+ # @param json [String]
21
+ # @raise [DeserializationError]
22
+ # @return [EvilEvents::Core::Events::AbstractEvent]
23
+ #
24
+ # @since 0.1.0
25
+ def deserialize(json)
26
+ raise DeserializationError unless json.is_a?(String)
27
+
28
+ begin
29
+ json_hash = ::JSON.parse(json, symbolize_names: true)
30
+ event_type = json_hash[:type]
31
+ event_payload = json_hash[:payload]
32
+ raise DeserializationError unless event_type && event_payload
33
+ rescue ::JSON::ParserError
34
+ raise DeserializationError
35
+ end
36
+
37
+ EvilEvents::BootPoint::System[:event_system].resolve_event_object(event_type, event_payload)
38
+ end
39
+ end
40
+
41
+ # @since 0.1.0
42
+ register(:json) { JSON }
43
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilEvents::Core::Events
4
+ # @api private
5
+ # @since 0.1.0
6
+ class Serializers
7
+ extend EvilEvents::Shared::DependencyContainer::Mixin
8
+
9
+ # @since 0.1.0
10
+ SerializersError = Class.new(StandardError)
11
+ # @since 0.1.0
12
+ SerializationError = Class.new(SerializersError)
13
+ # @since 0.1.0
14
+ DeserializationError = Class.new(SerializersError)
15
+ end
16
+ end