realm-core 0.7.1 → 0.7.3
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.
- checksums.yaml +4 -4
- data/README.md +40 -0
- data/Rakefile +19 -0
- metadata +25 -44
- data/lib/realm-core.rb +0 -6
- data/lib/realm.rb +0 -22
- data/lib/realm/action_handler.rb +0 -84
- data/lib/realm/action_handler/result.rb +0 -32
- data/lib/realm/builder.rb +0 -93
- data/lib/realm/command_handler.rb +0 -23
- data/lib/realm/config.rb +0 -57
- data/lib/realm/container.rb +0 -68
- data/lib/realm/context.rb +0 -37
- data/lib/realm/dependency.rb +0 -24
- data/lib/realm/dispatcher.rb +0 -74
- data/lib/realm/domain_resolver.rb +0 -59
- data/lib/realm/error.rb +0 -62
- data/lib/realm/event.rb +0 -56
- data/lib/realm/event_factory.rb +0 -53
- data/lib/realm/event_handler.rb +0 -102
- data/lib/realm/event_router.rb +0 -100
- data/lib/realm/event_router/gateway.rb +0 -50
- data/lib/realm/event_router/internal_loop_gateway.rb +0 -50
- data/lib/realm/health_status.rb +0 -46
- data/lib/realm/mixins/aggregate_member.rb +0 -25
- data/lib/realm/mixins/context_injection.rb +0 -49
- data/lib/realm/mixins/controller.rb +0 -53
- data/lib/realm/mixins/decorator.rb +0 -33
- data/lib/realm/mixins/dependency_injection.rb +0 -52
- data/lib/realm/mixins/reactive.rb +0 -32
- data/lib/realm/mixins/repository_helper.rb +0 -43
- data/lib/realm/multi_worker.rb +0 -30
- data/lib/realm/persistence.rb +0 -54
- data/lib/realm/persistence/repository_query_handler_adapter.rb +0 -24
- data/lib/realm/plugin.rb +0 -20
- data/lib/realm/query_handler.rb +0 -8
- data/lib/realm/runtime.rb +0 -61
- data/lib/realm/runtime/session.rb +0 -33
- data/lib/realm/types.rb +0 -9
data/lib/realm/event_factory.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'realm/error'
|
4
|
-
require 'realm/event'
|
5
|
-
|
6
|
-
module Realm
|
7
|
-
class EventFactory
|
8
|
-
def initialize(events_module)
|
9
|
-
@events_module = events_module
|
10
|
-
@event_class_map = collect_event_classes(events_module)
|
11
|
-
end
|
12
|
-
|
13
|
-
def create_event(event_type, correlate: nil, cause: nil, **attributes)
|
14
|
-
head = enhance_head(attributes.fetch(:head, {}), correlate: correlate, cause: cause)
|
15
|
-
body = attributes.fetch(:body, attributes.except(:head))
|
16
|
-
|
17
|
-
event_class_for(event_type).new(head: head, body: body)
|
18
|
-
end
|
19
|
-
|
20
|
-
def event_class_for(event_type)
|
21
|
-
return event_type if event_type.respond_to?(:new)
|
22
|
-
|
23
|
-
@event_class_map.fetch(event_type.to_s) do
|
24
|
-
raise EventClassMissing.new(event_type, @events_module)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def collect_event_classes(root_module)
|
31
|
-
root_module_str = root_module.to_s
|
32
|
-
root_module.constants.each_with_object({}) do |const_sym, all|
|
33
|
-
const = root_module.const_get(const_sym)
|
34
|
-
if !(const < Event) && const.to_s.start_with?(root_module_str)
|
35
|
-
all.merge!(collect_event_classes(const))
|
36
|
-
elsif const < Event
|
37
|
-
all[const.type] = const
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def enhance_head(head, correlate:, cause:)
|
43
|
-
head[:correlation_id] = correlate.head.correlation_id if correlate
|
44
|
-
if cause.is_a?(Event)
|
45
|
-
head[:cause_event_id] = cause.head.id
|
46
|
-
head[:correlation_id] ||= cause.head.correlation_id
|
47
|
-
elsif cause
|
48
|
-
head[:cause] = cause
|
49
|
-
end
|
50
|
-
head
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
data/lib/realm/event_handler.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/string'
|
4
|
-
require 'realm/persistence'
|
5
|
-
require 'realm/mixins/context_injection'
|
6
|
-
require 'realm/mixins/reactive'
|
7
|
-
require 'realm/mixins/repository_helper'
|
8
|
-
require 'realm/mixins/aggregate_member'
|
9
|
-
|
10
|
-
module Realm
|
11
|
-
class EventHandler
|
12
|
-
extend Mixins::ContextInjection::ClassMethods
|
13
|
-
include Mixins::AggregateMember
|
14
|
-
include Mixins::Reactive
|
15
|
-
include Mixins::RepositoryHelper
|
16
|
-
|
17
|
-
class RuntimeBound
|
18
|
-
delegate :identifier, :event_types, to: :@handler_class
|
19
|
-
|
20
|
-
def initialize(handler_class, runtime)
|
21
|
-
@handler_class = handler_class
|
22
|
-
@runtime = runtime
|
23
|
-
end
|
24
|
-
|
25
|
-
def call(event)
|
26
|
-
@handler_class.(event, runtime: @runtime.session(cause: event))
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class << self
|
31
|
-
attr_reader :trigger_mapping, :event_namespace
|
32
|
-
|
33
|
-
def bind_runtime(runtime)
|
34
|
-
RuntimeBound.new(self, runtime)
|
35
|
-
end
|
36
|
-
|
37
|
-
def call(event, runtime:)
|
38
|
-
new(runtime: runtime).(event)
|
39
|
-
end
|
40
|
-
|
41
|
-
def identifier(value = :undefined)
|
42
|
-
if value == :undefined
|
43
|
-
defined?(@identifier) ? @identifier : name.gsub(/(Domain|(Event)?Handlers?)/, '').underscore.gsub(%r{/+}, '-')
|
44
|
-
else
|
45
|
-
@identifier = value
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def event_types
|
50
|
-
defined?(@trigger_mapping) ? @trigger_mapping.keys.uniq : []
|
51
|
-
end
|
52
|
-
|
53
|
-
protected
|
54
|
-
|
55
|
-
def namespace(value)
|
56
|
-
@event_namespace = value
|
57
|
-
end
|
58
|
-
|
59
|
-
def on(*triggers, run: nil, **options, &block)
|
60
|
-
@method_triggers = triggers
|
61
|
-
@method_trigger_options = options # TODO: store and pass to gateway
|
62
|
-
return unless run || block
|
63
|
-
|
64
|
-
block = ->(event) { self.run(run, event.body) } if run
|
65
|
-
define_method("handle_#{triggers.join('_or_')}", &block)
|
66
|
-
end
|
67
|
-
|
68
|
-
def method_added(method_name)
|
69
|
-
super
|
70
|
-
return unless defined?(@method_triggers)
|
71
|
-
|
72
|
-
@trigger_mapping ||= {}
|
73
|
-
@method_triggers.each do |trigger|
|
74
|
-
(@trigger_mapping[trigger.to_sym] ||= []) << method_name
|
75
|
-
end
|
76
|
-
remove_instance_variable(:@method_triggers)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def initialize(runtime: nil)
|
81
|
-
@runtime = runtime
|
82
|
-
end
|
83
|
-
|
84
|
-
def call(event)
|
85
|
-
event_to_methods(event).each do |method_name|
|
86
|
-
send(method_name, event)
|
87
|
-
rescue Realm::Persistence::Conflict => e
|
88
|
-
context[:logger]&.warn(e.full_message)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
protected
|
93
|
-
|
94
|
-
delegate :context, to: :@runtime
|
95
|
-
|
96
|
-
private
|
97
|
-
|
98
|
-
def event_to_methods(event)
|
99
|
-
self.class.trigger_mapping.fetch_values(event.type.to_sym, :any) { [] }.flatten
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
data/lib/realm/event_router.rb
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/string'
|
4
|
-
require 'active_support/core_ext/hash'
|
5
|
-
require 'realm/error'
|
6
|
-
require 'realm/domain_resolver'
|
7
|
-
require 'realm/event_handler'
|
8
|
-
require 'realm/event_factory'
|
9
|
-
require 'realm/mixins/dependency_injection'
|
10
|
-
require_relative 'event_router/internal_loop_gateway'
|
11
|
-
|
12
|
-
module Realm
|
13
|
-
class EventRouter
|
14
|
-
include Mixins::DependencyInjection
|
15
|
-
inject DomainResolver
|
16
|
-
inject 'Realm::Runtime', lazy: true
|
17
|
-
|
18
|
-
def initialize(gateways_spec, prefix: nil)
|
19
|
-
@prefix = prefix
|
20
|
-
@auto_registered = false
|
21
|
-
@default_namespace = nil
|
22
|
-
init_gateways(gateways_spec)
|
23
|
-
end
|
24
|
-
|
25
|
-
def register(handler_class)
|
26
|
-
gateway_for(handler_class.try(:event_namespace)).register(handler_class)
|
27
|
-
end
|
28
|
-
|
29
|
-
def add_listener(event_type, listener, namespace: nil)
|
30
|
-
gateway_for(namespace).add_listener(event_type, listener)
|
31
|
-
end
|
32
|
-
|
33
|
-
def trigger(identifier, attributes = {})
|
34
|
-
namespace, event_type = identifier.to_s.include?('/') ? identifier.split('/') : [nil, identifier]
|
35
|
-
gateway_for(namespace).trigger(event_type, attributes)
|
36
|
-
end
|
37
|
-
|
38
|
-
def workers(*namespaces, **options)
|
39
|
-
auto_register_handlers
|
40
|
-
@gateways.filter_map do |(namespace, gateway)|
|
41
|
-
gateway.worker(**options) if namespaces.empty? || namespaces.include?(namespace)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def active_queues
|
46
|
-
auto_register_handlers
|
47
|
-
@gateways.values.reduce([]) do |queues, gateway|
|
48
|
-
queues + gateway.queues
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def init_gateways(gateways_spec)
|
55
|
-
auto_register_on_init = false
|
56
|
-
@gateways = gateways_spec.each_with_object({}) do |(namespace, config), gateways|
|
57
|
-
gateway_class = gateway_class(config.fetch(:type))
|
58
|
-
auto_register_on_init ||= gateway_class.auto_register_on_init
|
59
|
-
gateways[namespace] = instantiate_gateway(namespace, gateway_class, config)
|
60
|
-
@default_namespace = namespace if config[:default]
|
61
|
-
end
|
62
|
-
auto_register_handlers if auto_register_on_init
|
63
|
-
end
|
64
|
-
|
65
|
-
def gateway_class(type)
|
66
|
-
return InternalLoopGateway if type.to_s == 'internal_loop'
|
67
|
-
|
68
|
-
runtime.container.resolve("event_router.gateway_classes.#{type}")
|
69
|
-
end
|
70
|
-
|
71
|
-
def instantiate_gateway(namespace, klass, config)
|
72
|
-
klass.new(
|
73
|
-
namespace: namespace,
|
74
|
-
queue_prefix: @prefix,
|
75
|
-
event_factory: EventFactory.new(config.fetch(:events_module)),
|
76
|
-
runtime: runtime,
|
77
|
-
**config.except(:type, :default, :events_module),
|
78
|
-
)
|
79
|
-
end
|
80
|
-
|
81
|
-
def auto_register_handlers
|
82
|
-
return if @auto_registered || !domain_resolver
|
83
|
-
|
84
|
-
@auto_registered = true
|
85
|
-
domain_resolver.all_event_handlers.each { |klass| register(klass) }
|
86
|
-
end
|
87
|
-
|
88
|
-
def gateway_for(namespace)
|
89
|
-
@gateways.fetch(namespace.try(:to_sym) || default_namespace) do
|
90
|
-
raise "No event gateway for #{namespace || 'default'} namespace" # TODO: extract error class
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def default_namespace
|
95
|
-
return @default_namespace if @default_namespace
|
96
|
-
|
97
|
-
@gateways.keys[0] if @gateways.keys.size == 1
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Realm
|
4
|
-
class EventRouter
|
5
|
-
class Gateway
|
6
|
-
def self.auto_register_on_init
|
7
|
-
false
|
8
|
-
end
|
9
|
-
|
10
|
-
def initialize(event_factory:, namespace: :default, runtime: nil, **)
|
11
|
-
@namespace = namespace
|
12
|
-
@event_factory = event_factory
|
13
|
-
@runtime = runtime
|
14
|
-
end
|
15
|
-
|
16
|
-
def register(handler_class)
|
17
|
-
# TODO: validate event_types for existence of matching class
|
18
|
-
handler_class.event_types.each do |event_type|
|
19
|
-
add_listener(event_type, handler_class.bind_runtime(@runtime))
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def add_listener(event_type, listener)
|
24
|
-
raise NotImplementedError
|
25
|
-
end
|
26
|
-
|
27
|
-
def trigger(event_type, attributes = {})
|
28
|
-
raise NotImplementedError
|
29
|
-
end
|
30
|
-
|
31
|
-
def worker(*)
|
32
|
-
nil
|
33
|
-
end
|
34
|
-
|
35
|
-
def cleanup
|
36
|
-
# do nothing
|
37
|
-
end
|
38
|
-
|
39
|
-
def queues
|
40
|
-
[]
|
41
|
-
end
|
42
|
-
|
43
|
-
protected
|
44
|
-
|
45
|
-
def create_event(event_type, attributes = {})
|
46
|
-
@event_factory.create_event(event_type, **attributes)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './gateway'
|
4
|
-
|
5
|
-
module Realm
|
6
|
-
class EventRouter
|
7
|
-
class InternalLoopGateway < Gateway
|
8
|
-
def self.auto_register_on_init
|
9
|
-
true
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize(isolated: false, **)
|
13
|
-
super
|
14
|
-
@listener_map = {}
|
15
|
-
@isolated = isolated
|
16
|
-
gateways << self
|
17
|
-
end
|
18
|
-
|
19
|
-
def add_listener(event_type, listener)
|
20
|
-
(@listener_map[event_type.to_sym] ||= []) << listener
|
21
|
-
end
|
22
|
-
|
23
|
-
def trigger(event_type, attributes = {})
|
24
|
-
create_event(event_type, attributes).tap do |event|
|
25
|
-
gateways.each { |gateway| gateway.handle(event_type, event) }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def purge!
|
30
|
-
gateways.clear
|
31
|
-
end
|
32
|
-
|
33
|
-
protected
|
34
|
-
|
35
|
-
def handle(event_type, event)
|
36
|
-
find_listeners(event_type).each { |listener| listener.(event) }
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def find_listeners(event_type)
|
42
|
-
@listener_map.fetch_values(event_type.to_sym, :any) { [] }.flatten
|
43
|
-
end
|
44
|
-
|
45
|
-
def gateways
|
46
|
-
@isolated ? (@gateways ||= []) : (@@gateways ||= []) # rubocop:disable Style/ClassVars
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
data/lib/realm/health_status.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/object/blank'
|
4
|
-
|
5
|
-
module Realm
|
6
|
-
class HealthStatus
|
7
|
-
CODES = %i[green yellow red].freeze
|
8
|
-
attr_reader :code, :issues
|
9
|
-
|
10
|
-
class << self
|
11
|
-
def [](code, *issues)
|
12
|
-
new(code, issues.flatten)
|
13
|
-
end
|
14
|
-
|
15
|
-
def from_issues(issues)
|
16
|
-
new(issues.blank? ? :green : :red, issues)
|
17
|
-
end
|
18
|
-
|
19
|
-
def combine(component_map)
|
20
|
-
code_index = component_map.values.map { |i| CODES.index(i.code) }.max
|
21
|
-
new(CODES[code_index || 0], [], component_map)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def for_component(*names)
|
26
|
-
@component_map.dig(*names)
|
27
|
-
end
|
28
|
-
|
29
|
-
def to_h
|
30
|
-
hash = { status: @code }
|
31
|
-
hash[:issues] = @issues if @issues.present?
|
32
|
-
hash[:components] = @component_map.transform_values(&:to_h) if @component_map.present?
|
33
|
-
hash
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def initialize(code, issues = [], component_map = {})
|
39
|
-
raise ArgumentError, "Invalid status code #{code}" unless CODES.include?(code)
|
40
|
-
|
41
|
-
@code = code
|
42
|
-
@issues = issues.freeze
|
43
|
-
@component_map = component_map.freeze
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Realm
|
4
|
-
module Mixins
|
5
|
-
module AggregateMember
|
6
|
-
def self.included(base)
|
7
|
-
base.extend(ClassMethods)
|
8
|
-
end
|
9
|
-
|
10
|
-
def aggregate
|
11
|
-
self.class.aggregate
|
12
|
-
end
|
13
|
-
|
14
|
-
module ClassMethods
|
15
|
-
def aggregate
|
16
|
-
@aggregate ||= begin
|
17
|
-
module_chain = name.split('::')
|
18
|
-
domain_index = module_chain.index('Domain')
|
19
|
-
domain_index && module_chain[domain_index + 1].underscore.to_sym
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'realm/error'
|
4
|
-
|
5
|
-
module Realm
|
6
|
-
module Mixins
|
7
|
-
module ContextInjection
|
8
|
-
def self.included(base)
|
9
|
-
base.extend(ClassMethods)
|
10
|
-
base.prepend(Initializer)
|
11
|
-
end
|
12
|
-
|
13
|
-
module ClassMethods
|
14
|
-
def inject(*names, &block)
|
15
|
-
names.each do |name|
|
16
|
-
define_method(name) do
|
17
|
-
raise Realm::DependencyMissing, name unless context.key?(name)
|
18
|
-
|
19
|
-
return context[name] unless block
|
20
|
-
|
21
|
-
var = "@#{name}"
|
22
|
-
return instance_variable_get(var) if instance_variable_defined?(var)
|
23
|
-
|
24
|
-
instance_variable_set(var, block.(context[name]))
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
module Initializer
|
31
|
-
def initialize(*args, context: nil, **kwargs)
|
32
|
-
@context = context || context_from_root_module || {}
|
33
|
-
super(*args, **kwargs)
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def context_from_root_module
|
39
|
-
root_module = self.class.module_parents[-2]
|
40
|
-
root_module.realm.context if root_module.respond_to?(:realm)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
protected
|
45
|
-
|
46
|
-
attr_reader :context
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|