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/config.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/string'
|
4
|
-
require 'dry-initializer'
|
5
|
-
|
6
|
-
module Realm
|
7
|
-
class Config
|
8
|
-
extend Dry::Initializer
|
9
|
-
|
10
|
-
option :root_module
|
11
|
-
option :database_url, default: proc {}
|
12
|
-
option :prefix, default: proc {}
|
13
|
-
option :namespace, default: proc { root_module.to_s.underscore }
|
14
|
-
option :domain_module, default: proc { "#{root_module}::Domain" }
|
15
|
-
option :engine_class, default: proc { "#{root_module}::Engine" }
|
16
|
-
option :engine_path, default: proc { engine_class&.to_s&.safe_constantize&.root }
|
17
|
-
option :logger, default: proc {}
|
18
|
-
option :plugins, default: proc { [] }, reader: false
|
19
|
-
option :dependencies, default: proc { {} }
|
20
|
-
option :persistence_gateway, default: proc { database_url && { type: :rom, url: database_url } }, reader: false
|
21
|
-
option :event_gateway, default: proc {}, reader: false
|
22
|
-
option :event_gateways, default: proc {
|
23
|
-
@event_gateway ? { default: { **@event_gateway, default: true } } : {}
|
24
|
-
}
|
25
|
-
|
26
|
-
def plugins
|
27
|
-
Array(@plugins)
|
28
|
-
end
|
29
|
-
|
30
|
-
def persistence_gateway
|
31
|
-
return {} unless @persistence_gateway
|
32
|
-
|
33
|
-
class_path = engine_path && "#{engine_path}/app/persistence/#{namespace}"
|
34
|
-
repos_path = class_path && "#{class_path}/repositories"
|
35
|
-
repos_module = "#{root_module}::Repositories"
|
36
|
-
{
|
37
|
-
root_module: root_module,
|
38
|
-
class_path: class_path,
|
39
|
-
repos_path: repos_path,
|
40
|
-
repos_module: repos_module,
|
41
|
-
migration_path: engine_path && "#{engine_path}/db/migrate",
|
42
|
-
repositories: repositories(repos_path, repos_module),
|
43
|
-
}.merge(@persistence_gateway)
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def repositories(repos_path, repos_module)
|
49
|
-
return [] unless repos_path
|
50
|
-
|
51
|
-
Dir[File.join(repos_path, '**', '*.rb')].each_with_object([]) do |filename, all|
|
52
|
-
matches = %r{^#{repos_path}/(.+)\.rb$}.match(filename)
|
53
|
-
all << "#{repos_module}::#{matches[1].camelize}".constantize if matches
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/realm/container.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'dry-container'
|
4
|
-
require 'active_support/core_ext/string'
|
5
|
-
require 'active_support/core_ext/object/try'
|
6
|
-
require 'realm/error'
|
7
|
-
|
8
|
-
module Realm
|
9
|
-
class Container
|
10
|
-
include Dry::Container::Mixin
|
11
|
-
include Enumerable
|
12
|
-
|
13
|
-
def self.[](object)
|
14
|
-
object.is_a?(Container) ? object : Container.new(object)
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(hash = {})
|
18
|
-
register_all(hash)
|
19
|
-
end
|
20
|
-
|
21
|
-
def register(key, contents = nil, options = {}, &block)
|
22
|
-
options[:klass] ||= contents.class if contents && !contents.is_a?(::Hash)
|
23
|
-
super(key, contents, options, &block)
|
24
|
-
end
|
25
|
-
|
26
|
-
def register_all(hash)
|
27
|
-
hash.each_pair do |key, value|
|
28
|
-
register(key, value)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def register_factory(klass, *args, as: nil, memoize: true, **kwargs) # rubocop:disable Naming/MethodParameterName
|
33
|
-
register(as || klass, klass: klass, memoize: memoize) do
|
34
|
-
create(klass, *args, **kwargs)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def create(klass, *args, **kwargs)
|
39
|
-
(klass.try(:dependencies) || []).each do |d|
|
40
|
-
fn = -> { resolve_dependable(sanitize_dependable(d.dependable), d.optional?) }
|
41
|
-
kwargs[d.name] = d.lazy? ? fn : fn.call
|
42
|
-
end
|
43
|
-
klass.new(*args, **kwargs)
|
44
|
-
end
|
45
|
-
|
46
|
-
def [](key)
|
47
|
-
resolve(key) if key?(key)
|
48
|
-
end
|
49
|
-
|
50
|
-
def resolve_all(klass)
|
51
|
-
_container.each_with_object([]) do |(_, item), all|
|
52
|
-
all << item.call if item.options[:klass] <= klass
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def sanitize_dependable(dependable)
|
59
|
-
dependable.is_a?(String) && dependable.match(/^[A-Z]/) ? dependable.constantize : dependable
|
60
|
-
end
|
61
|
-
|
62
|
-
def resolve_dependable(dependable, optional)
|
63
|
-
raise DependencyMissing, dependable unless optional || key?(dependable)
|
64
|
-
|
65
|
-
self[dependable]
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
data/lib/realm/context.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'realm/container'
|
4
|
-
|
5
|
-
module Realm
|
6
|
-
class Context
|
7
|
-
include Enumerable
|
8
|
-
|
9
|
-
def initialize(*containers)
|
10
|
-
@containers = containers.map { |c| Container[c] }
|
11
|
-
end
|
12
|
-
|
13
|
-
def [](name)
|
14
|
-
@containers.each do |container|
|
15
|
-
return container[name] if container.key?(name)
|
16
|
-
end
|
17
|
-
nil
|
18
|
-
end
|
19
|
-
|
20
|
-
def key?(name)
|
21
|
-
@containers.any? { |container| container.key?(name) }
|
22
|
-
end
|
23
|
-
|
24
|
-
def merge(container_like)
|
25
|
-
container_like.blank? ? self : self.class.new(container_like, *@containers)
|
26
|
-
end
|
27
|
-
|
28
|
-
def each(&block)
|
29
|
-
@containers.each { |container| container.each(&block) }
|
30
|
-
end
|
31
|
-
|
32
|
-
# Just for testing
|
33
|
-
def override!(container)
|
34
|
-
@containers.prepend(container)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/lib/realm/dependency.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/string'
|
4
|
-
|
5
|
-
module Realm
|
6
|
-
class Dependency
|
7
|
-
attr_reader :dependable, :name
|
8
|
-
|
9
|
-
def initialize(dependable, as: nil, optional: false, lazy: false) # rubocop:disable Naming/MethodParameterName
|
10
|
-
@dependable = dependable
|
11
|
-
@name = as || dependable.to_s.demodulize.underscore.to_sym
|
12
|
-
@optional = optional
|
13
|
-
@lazy = lazy
|
14
|
-
end
|
15
|
-
|
16
|
-
def optional?
|
17
|
-
@optional
|
18
|
-
end
|
19
|
-
|
20
|
-
def lazy?
|
21
|
-
@lazy
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/lib/realm/dispatcher.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/string'
|
4
|
-
require 'realm/query_handler'
|
5
|
-
require 'realm/command_handler'
|
6
|
-
require 'realm/domain_resolver'
|
7
|
-
require 'realm/error'
|
8
|
-
require 'realm/mixins/dependency_injection'
|
9
|
-
require 'realm/persistence/repository_query_handler_adapter'
|
10
|
-
|
11
|
-
module Realm
|
12
|
-
class Dispatcher
|
13
|
-
include Mixins::DependencyInjection
|
14
|
-
inject DomainResolver
|
15
|
-
|
16
|
-
def initialize(runtime)
|
17
|
-
@runtime = runtime
|
18
|
-
@threads = []
|
19
|
-
end
|
20
|
-
|
21
|
-
def query(identifier, params = {})
|
22
|
-
callable, action = get_callable(QueryHandler, identifier)
|
23
|
-
callable, action = get_repo_adapter(identifier) unless callable
|
24
|
-
raise QueryHandlerMissing, identifier unless callable
|
25
|
-
|
26
|
-
dispatch(callable, action, params)
|
27
|
-
end
|
28
|
-
|
29
|
-
def run(identifier, params = {})
|
30
|
-
callable, action = get_callable(CommandHandler, identifier)
|
31
|
-
raise CommandHandlerMissing, identifier unless callable
|
32
|
-
|
33
|
-
dispatch(callable, action, params)
|
34
|
-
end
|
35
|
-
|
36
|
-
def run_as_job(identifier, params = {})
|
37
|
-
callable, action = get_callable(CommandHandler, identifier)
|
38
|
-
raise CommandHandlerMissing, identifier unless callable
|
39
|
-
|
40
|
-
@threads.delete_if(&:stop?)
|
41
|
-
@threads << Thread.new do # TODO: back by SQS
|
42
|
-
result = dispatch(callable, action, params)
|
43
|
-
yield result if block_given?
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Blocks until all jobs are finished. Useful mainly in tests.
|
48
|
-
def wait_for_jobs
|
49
|
-
@threads.each(&:join)
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
attr_reader :runtime
|
55
|
-
|
56
|
-
def dispatch(callable, action, params)
|
57
|
-
arguments = { action: action, params: params, runtime: runtime }.compact
|
58
|
-
callable.(**arguments)
|
59
|
-
end
|
60
|
-
|
61
|
-
def get_callable(type, identifier)
|
62
|
-
return [identifier, nil] if identifier.respond_to?(:call)
|
63
|
-
|
64
|
-
domain_resolver.get_handler_with_action(type, identifier)
|
65
|
-
end
|
66
|
-
|
67
|
-
def get_repo_adapter(identifier)
|
68
|
-
parts = identifier.to_s.split('.')
|
69
|
-
return [nil, nil] unless parts.size == 2 && runtime&.context&.key?("#{parts[0]}_repo")
|
70
|
-
|
71
|
-
[Persistence::RepositoryQueryHandlerAdapter.new(runtime.context["#{parts[0]}_repo"]), parts[1].to_sym]
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/string'
|
4
|
-
require 'realm/command_handler'
|
5
|
-
require 'realm/query_handler'
|
6
|
-
require 'realm/event_handler'
|
7
|
-
require 'realm/event'
|
8
|
-
|
9
|
-
module Realm
|
10
|
-
class DomainResolver
|
11
|
-
DOMAIN_CLASS_TYPES = [CommandHandler, QueryHandler, EventHandler].freeze
|
12
|
-
|
13
|
-
def initialize(domain_module = nil)
|
14
|
-
# nil domain resolver is useful in tests
|
15
|
-
@domain_module = domain_module
|
16
|
-
@index = DOMAIN_CLASS_TYPES.map { |t| [t, {}] }.to_h
|
17
|
-
scan(domain_module) if domain_module
|
18
|
-
end
|
19
|
-
|
20
|
-
def get_handler_with_action(type, identifier)
|
21
|
-
handlers = @index[type]
|
22
|
-
return [handlers[identifier], :handle] if handlers.key?(identifier)
|
23
|
-
|
24
|
-
# The last part of the identifier can action method name inside the handler
|
25
|
-
parts = identifier.split('.')
|
26
|
-
handler_part = parts[..-2].join('.')
|
27
|
-
action = parts[-1]
|
28
|
-
return [handlers[handler_part], action.to_sym] if handlers.key?(handler_part)
|
29
|
-
|
30
|
-
[nil, nil]
|
31
|
-
end
|
32
|
-
|
33
|
-
def all_event_handlers
|
34
|
-
@index[EventHandler].values
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def scan(root_module)
|
40
|
-
root_module_str = root_module.to_s
|
41
|
-
root_module.constants.each do |const_sym|
|
42
|
-
const = root_module.const_get(const_sym)
|
43
|
-
next unless const.is_a?(Module) && !(const < Event) && const.to_s.start_with?(root_module_str)
|
44
|
-
|
45
|
-
type = DOMAIN_CLASS_TYPES.find { |t| const < t }
|
46
|
-
next scan(const) unless type
|
47
|
-
|
48
|
-
register(type, const)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def register(type, const)
|
53
|
-
# Remove domain module prefix and handler type suffixes
|
54
|
-
operation_type = type.to_s.demodulize.sub('Handler', '')
|
55
|
-
identifier = const.to_s.gsub(/(^#{@domain_module})|((#{operation_type})?Handlers?)/, '')
|
56
|
-
@index[type][identifier.underscore.gsub(%r{(^/+)|(/+$)}, '').gsub(%r{/+}, '.')] = const
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
data/lib/realm/error.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Realm
|
4
|
-
class Error < StandardError
|
5
|
-
def self.[](default_msg)
|
6
|
-
Class.new(Realm::Error) do
|
7
|
-
define_method(:initialize) do |msg = default_msg|
|
8
|
-
super(msg)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class QueryHandlerMissing < Error
|
15
|
-
def initialize(query_name, msg: "Cannot find handler for query '#{query_name}'")
|
16
|
-
super(msg)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class CommandHandlerMissing < Error
|
21
|
-
def initialize(command_name, msg: "Cannot find handler for command '#{command_name}'")
|
22
|
-
super(msg)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class CannotHandleAction < Error
|
27
|
-
def initialize(handler, action, msg: "#{handler} cannot handle action '#{action}'")
|
28
|
-
super(msg)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class DependencyMissing < Error
|
33
|
-
def initialize(dependency_name, msg: "Dependency '#{dependency_name}' missing in container")
|
34
|
-
super(msg)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
class EventClassMissing < Error
|
39
|
-
def initialize(identifier, events_module, msg: "Cannot find event class for #{identifier} in #{events_module}")
|
40
|
-
super(msg)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class InvalidParams < Error
|
45
|
-
def initialize(validation_result, msg: "Validation failed: #{validation_result.errors.to_h}")
|
46
|
-
@validation_result = validation_result
|
47
|
-
super(msg)
|
48
|
-
end
|
49
|
-
|
50
|
-
def params
|
51
|
-
@validation_result.to_h
|
52
|
-
end
|
53
|
-
|
54
|
-
def messages
|
55
|
-
@validation_result.errors.to_h
|
56
|
-
end
|
57
|
-
|
58
|
-
def full_messages
|
59
|
-
@validation_result.errors(full: true).to_h
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
data/lib/realm/event.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'securerandom'
|
4
|
-
require 'active_support/core_ext/hash'
|
5
|
-
require 'active_support/core_ext/string'
|
6
|
-
require 'dry-struct'
|
7
|
-
require 'realm/types'
|
8
|
-
|
9
|
-
module Realm
|
10
|
-
class Event < Dry::Struct
|
11
|
-
T = Realm::Types
|
12
|
-
|
13
|
-
transform_keys(&:to_sym)
|
14
|
-
|
15
|
-
attribute :head do
|
16
|
-
attribute :id, T::Strict::String
|
17
|
-
attribute :triggered_at, T::JSON::Time
|
18
|
-
attribute? :version, T::Coercible::String
|
19
|
-
attribute? :origin, T::Strict::String
|
20
|
-
attribute :correlation_id, T::Strict::String
|
21
|
-
attribute? :cause_event_id, T::Strict::String
|
22
|
-
attribute? :cause, T::Strict::String
|
23
|
-
end
|
24
|
-
|
25
|
-
class << self
|
26
|
-
def new(attributes = {})
|
27
|
-
head = {
|
28
|
-
id: SecureRandom.uuid,
|
29
|
-
correlation_id: SecureRandom.uuid,
|
30
|
-
triggered_at: Time.now,
|
31
|
-
version: 1, # until we need breaking change (anything except adding attribute) all events are version 1
|
32
|
-
}.merge(attributes.fetch(:head, {}))
|
33
|
-
body = attributes[:body] || attributes.except(:head)
|
34
|
-
super({ head: head }.merge(body.empty? ? {} : { body: body }))
|
35
|
-
end
|
36
|
-
|
37
|
-
def type
|
38
|
-
@type ||= name.demodulize.sub('Event', '').underscore
|
39
|
-
end
|
40
|
-
|
41
|
-
protected
|
42
|
-
|
43
|
-
def body_struct(&block)
|
44
|
-
attribute(:body, &block)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def type
|
49
|
-
self.class.type
|
50
|
-
end
|
51
|
-
|
52
|
-
def to_json(*args)
|
53
|
-
JSON.generate(to_h, *args)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|