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
@@ -1,53 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/module/introspection'
|
4
|
-
require 'active_support/core_ext/class/attribute'
|
5
|
-
|
6
|
-
module Realm
|
7
|
-
module Mixins
|
8
|
-
module Controller
|
9
|
-
def self.included(base)
|
10
|
-
base.class_attribute(:aggregate_name)
|
11
|
-
base.extend(ClassMethods)
|
12
|
-
end
|
13
|
-
|
14
|
-
def domain_runtime
|
15
|
-
@domain_runtime ||= root_domain_runtime.session(domain_context)
|
16
|
-
end
|
17
|
-
|
18
|
-
def domain_context
|
19
|
-
{}
|
20
|
-
end
|
21
|
-
|
22
|
-
def query(identifier, params = {})
|
23
|
-
domain_runtime.query(get_dispatchable(identifier), params)
|
24
|
-
end
|
25
|
-
|
26
|
-
def run(identifier, params = {})
|
27
|
-
domain_runtime.run(get_dispatchable(identifier), params)
|
28
|
-
end
|
29
|
-
|
30
|
-
def run_as_job(identifier, params = {})
|
31
|
-
domain_runtime.run_as_job(get_dispatchable(identifier), params)
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def get_dispatchable(identifier)
|
37
|
-
return identifier if identifier.respond_to?(:call)
|
38
|
-
|
39
|
-
[aggregate_name, identifier].compact.join('.')
|
40
|
-
end
|
41
|
-
|
42
|
-
def root_domain_runtime
|
43
|
-
self.class.module_parents[-2].realm
|
44
|
-
end
|
45
|
-
|
46
|
-
module ClassMethods
|
47
|
-
def with_aggregate(name)
|
48
|
-
self.aggregate_name = name
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Realm
|
4
|
-
module Mixins
|
5
|
-
module Decorator
|
6
|
-
def self.[](decorated) # rubocop:disable Metrics/MethodLength
|
7
|
-
Module.new do
|
8
|
-
def method_missing(...)
|
9
|
-
_decorated.send(...)
|
10
|
-
end
|
11
|
-
|
12
|
-
def respond_to_missing?(...)
|
13
|
-
_decorated.respond_to?(...)
|
14
|
-
end
|
15
|
-
|
16
|
-
if decorated.to_s[0] == '@'
|
17
|
-
define_method :initialize do |value|
|
18
|
-
instance_variable_set(decorated, value)
|
19
|
-
end
|
20
|
-
|
21
|
-
define_method :_decorated do
|
22
|
-
instance_variable_get(decorated)
|
23
|
-
end
|
24
|
-
else
|
25
|
-
define_method :_decorated do
|
26
|
-
send(decorated)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'realm/dependency'
|
4
|
-
|
5
|
-
module Realm
|
6
|
-
module Mixins
|
7
|
-
module DependencyInjection
|
8
|
-
def self.included(base)
|
9
|
-
base.extend(ClassMethods)
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
def new(*args, **kwargs, &block)
|
14
|
-
instance = allocate
|
15
|
-
deps.each { |d| define_dependency_method(instance, kwargs, d) }
|
16
|
-
kwargs_without_dependencies = kwargs.reject { |k, _| deps.any? { |d| d.name == k } }
|
17
|
-
instance.send(:initialize, *args, **kwargs_without_dependencies, &block)
|
18
|
-
instance
|
19
|
-
end
|
20
|
-
|
21
|
-
def inject(*dependables, **options)
|
22
|
-
deps.concat(dependables.map { |d| Dependency.new(d, **options) })
|
23
|
-
end
|
24
|
-
|
25
|
-
def dependencies
|
26
|
-
deps.freeze
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def deps
|
32
|
-
@deps ||= []
|
33
|
-
end
|
34
|
-
|
35
|
-
def define_dependency_method(instance, kwargs, spec)
|
36
|
-
dependency = kwargs[spec.name]
|
37
|
-
instance.singleton_class.class_eval do
|
38
|
-
define_method(spec.name) do
|
39
|
-
return dependency unless spec.lazy?
|
40
|
-
|
41
|
-
var = "@#{spec.name}"
|
42
|
-
return instance_variable_get(var) if instance_variable_defined?(var)
|
43
|
-
|
44
|
-
instance_variable_set(var, dependency.respond_to?(:call) ? dependency.call : dependency)
|
45
|
-
end
|
46
|
-
protected spec.name
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'realm/error'
|
4
|
-
|
5
|
-
module Realm
|
6
|
-
module Mixins
|
7
|
-
module Reactive
|
8
|
-
protected
|
9
|
-
|
10
|
-
def run(command, params = {})
|
11
|
-
parts = command.to_s.split('.')
|
12
|
-
parts.prepend(aggregate) if parts.size == 1 && respond_to?(:aggregate) && aggregate
|
13
|
-
@runtime.run(parts.join('.'), params.to_h)
|
14
|
-
end
|
15
|
-
|
16
|
-
def trigger(event_type, attributes = {})
|
17
|
-
attributes = attributes.to_h
|
18
|
-
head = { origin: origin(caller_locations(1, 1)) }.merge(attributes.fetch(:head, {}))
|
19
|
-
final_attrs = attributes.merge(head: head)
|
20
|
-
final_attrs[:cause] ||= context[:cause] if context.key?(:cause)
|
21
|
-
@runtime.trigger(event_type, final_attrs)
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
# Detects the class and method from which this event is triggered
|
27
|
-
def origin(backtrace)
|
28
|
-
[self.class.name, backtrace[0].to_s.match(/`([^']+)'/)&.then { |m| "##{m[1]}" }].join
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'realm/error'
|
4
|
-
|
5
|
-
module Realm
|
6
|
-
module Mixins
|
7
|
-
module RepositoryHelper
|
8
|
-
class OnlyOneWriteRepo < Realm::Error['You can have only one read/write repo per handler']; end
|
9
|
-
class InjectingRepoOutsideAggregate < Realm::Error['Cannot auto inject repository outside of an aggregate']; end
|
10
|
-
|
11
|
-
def self.included(base)
|
12
|
-
base.extend(ClassMethods)
|
13
|
-
end
|
14
|
-
|
15
|
-
module ClassMethods
|
16
|
-
protected
|
17
|
-
|
18
|
-
def use_repo(*names, readonly: self < Realm::QueryHandler)
|
19
|
-
raise OnlyOneWriteRepo if !readonly && (names.size > 1 || defined?(@write_repo_injected))
|
20
|
-
|
21
|
-
names << default_repo_name if names.empty?
|
22
|
-
names.each { |name| inject_repo(name, readonly) }
|
23
|
-
@write_repo_injected = true unless readonly
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def inject_repo(name, readonly)
|
29
|
-
repo_name = "#{name}_repo"
|
30
|
-
return inject(repo_name) unless readonly
|
31
|
-
|
32
|
-
inject(repo_name) { |repo| repo.respond_to?(:readonly) ? repo.readonly : repo }
|
33
|
-
end
|
34
|
-
|
35
|
-
def default_repo_name
|
36
|
-
raise InjectingRepoOutsideAggregate unless respond_to?(:aggregate)
|
37
|
-
|
38
|
-
aggregate
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
data/lib/realm/multi_worker.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Realm
|
4
|
-
class MultiWorker
|
5
|
-
def initialize(workers = [])
|
6
|
-
@workers = workers
|
7
|
-
end
|
8
|
-
|
9
|
-
def start(*args)
|
10
|
-
@workers.each { |w| w.start(*args) }
|
11
|
-
self
|
12
|
-
end
|
13
|
-
|
14
|
-
def stop(timeout: 30)
|
15
|
-
@workers.each { |w| w.stop(timeout: timeout) }
|
16
|
-
end
|
17
|
-
|
18
|
-
def join
|
19
|
-
@workers.each(&:join)
|
20
|
-
end
|
21
|
-
|
22
|
-
def run
|
23
|
-
%w[INT TERM].each do |signal|
|
24
|
-
Signal.trap(signal) { stop }
|
25
|
-
end
|
26
|
-
start
|
27
|
-
join
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
data/lib/realm/persistence.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/string'
|
4
|
-
require 'realm/error'
|
5
|
-
|
6
|
-
module Realm
|
7
|
-
class Persistence
|
8
|
-
class InvalidPersistanceType < Realm::Error; end
|
9
|
-
class Conflict < Realm::Error; end
|
10
|
-
|
11
|
-
class RelationIsReadOnly < Realm::Error
|
12
|
-
def initialize(relation, msg: "Cannot write using read-only relation #{relation.class}")
|
13
|
-
super(msg)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class RepositoryIsReadOnly < Realm::Error
|
18
|
-
def initialize(repo, msg: "Cannot write using read-only repository #{repo.class}")
|
19
|
-
super(msg)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.setup(...)
|
24
|
-
new(...).setup
|
25
|
-
end
|
26
|
-
|
27
|
-
def initialize(container, repositories)
|
28
|
-
@container = container
|
29
|
-
@repositories = repositories
|
30
|
-
end
|
31
|
-
|
32
|
-
def setup
|
33
|
-
register_repos
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def gateway
|
39
|
-
@gateway ||= @container.resolve('persistence.gateway')
|
40
|
-
end
|
41
|
-
|
42
|
-
def register_repos
|
43
|
-
@repositories.each do |repo_class|
|
44
|
-
@container.register_factory(repo_class, gateway, as: "#{repo_class.name.demodulize.underscore}_repo")
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def constantize(*parts)
|
49
|
-
return parts[0] unless parts[0].is_a?(String)
|
50
|
-
|
51
|
-
parts.join('::').safe_constantize
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'realm/persistence'
|
4
|
-
require 'realm/error'
|
5
|
-
|
6
|
-
module Realm
|
7
|
-
class Persistence
|
8
|
-
class QueryCannotModifyState < Realm::Error; end
|
9
|
-
|
10
|
-
class RepositoryQueryHandlerAdapter
|
11
|
-
def initialize(repo)
|
12
|
-
@repo = repo.respond_to?(:readonly) ? repo.readonly : repo
|
13
|
-
end
|
14
|
-
|
15
|
-
def call(action:, params: {}, **)
|
16
|
-
raise CannotHandleAction.new(self, action) unless @repo.respond_to?(action)
|
17
|
-
|
18
|
-
@repo.send(action, **params)
|
19
|
-
rescue RepositoryIsReadOnly
|
20
|
-
raise QueryCannotModifyState
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/lib/realm/plugin.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/class'
|
4
|
-
require 'active_support/core_ext/string'
|
5
|
-
|
6
|
-
module Realm
|
7
|
-
class Plugin
|
8
|
-
class << self
|
9
|
-
def plugin_name(value = :not_provided)
|
10
|
-
@plugin_name = value.to_sym unless value == :not_provided
|
11
|
-
@plugin_name = name.split('::')[-2].underscore.to_sym unless defined?(@plugin_name)
|
12
|
-
@plugin_name
|
13
|
-
end
|
14
|
-
|
15
|
-
def setup(_config, _container)
|
16
|
-
raise NotImplementedError
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/lib/realm/query_handler.rb
DELETED
data/lib/realm/runtime.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/module/delegation'
|
4
|
-
require 'active_support/core_ext/object/try'
|
5
|
-
require 'realm/context'
|
6
|
-
require 'realm/container'
|
7
|
-
require 'realm/dispatcher'
|
8
|
-
require 'realm/event_router'
|
9
|
-
require 'realm/multi_worker'
|
10
|
-
require 'realm/health_status'
|
11
|
-
require 'realm/runtime/session'
|
12
|
-
|
13
|
-
module Realm
|
14
|
-
class Runtime
|
15
|
-
delegate :query, :run, :run_as_job, :wait_for_jobs, to: :dispatcher
|
16
|
-
delegate :trigger, :add_listener, to: :event_router
|
17
|
-
delegate :[], to: :context
|
18
|
-
attr_reader :container
|
19
|
-
|
20
|
-
def initialize(container = Container.new)
|
21
|
-
@container = Container[container]
|
22
|
-
end
|
23
|
-
|
24
|
-
def context
|
25
|
-
@context ||= Context.new(@container)
|
26
|
-
end
|
27
|
-
|
28
|
-
def session(context = {})
|
29
|
-
context.blank? ? self : Session.new(self, context)
|
30
|
-
end
|
31
|
-
|
32
|
-
def worker(*args)
|
33
|
-
MultiWorker.new(event_router.try(:workers, *args) || [])
|
34
|
-
end
|
35
|
-
|
36
|
-
def health
|
37
|
-
component_statuses = container.each_with_object({}) do |(name, component), map|
|
38
|
-
map[name] = component.health if component.respond_to?(:health) && !component.is_a?(Runtime)
|
39
|
-
end
|
40
|
-
HealthStatus.combine(component_statuses)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Get all active messaging queues. For maintenance purpose only.
|
44
|
-
# TODO: Introduce component container and allow to call those method directly on components instead of
|
45
|
-
# polluting runtime
|
46
|
-
# Example: engine.realm.components.find(type: Realm::EventRouter::SNSGateway).try(:active_queues)
|
47
|
-
def active_queues
|
48
|
-
event_router.try(:active_queues) || []
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def dispatcher
|
54
|
-
@dispatcher ||= container.create(Dispatcher, self)
|
55
|
-
end
|
56
|
-
|
57
|
-
def event_router
|
58
|
-
@container[EventRouter]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'realm/dispatcher'
|
4
|
-
|
5
|
-
module Realm
|
6
|
-
class Runtime
|
7
|
-
class Session
|
8
|
-
delegate :query, :run, :run_as_job, :wait_for_jobs, to: :dispatcher
|
9
|
-
delegate :add_listener, :trigger, :worker, to: :@runtime
|
10
|
-
delegate :[], to: :context
|
11
|
-
attr_reader :context
|
12
|
-
|
13
|
-
def initialize(runtime, context)
|
14
|
-
@runtime = runtime
|
15
|
-
@context = runtime.context.merge(context)
|
16
|
-
end
|
17
|
-
|
18
|
-
def session(context = {})
|
19
|
-
context.blank? ? self : self.class.new(self, context)
|
20
|
-
end
|
21
|
-
|
22
|
-
def container
|
23
|
-
@runtime.container
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def dispatcher
|
29
|
-
@dispatcher ||= container.create(Dispatcher, self)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|