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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48d73715170e2bfb91f817fe7f09816980939bfd51d56e061a088908af40dd08
|
4
|
+
data.tar.gz: bde68574affd81f8eaecb821921c6dba91fe151eaa9b1703cdf31fff14e934cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff5149ff935de4a9599679f6daf246af8c43a06b3fab9d35f941a5c7d84b05b6557b4ed13487b56f127afaabe7a4868a8900d918004214f0ab13ba359763db5f
|
7
|
+
data.tar.gz: 681487eb34d5d79f090eb505966fda04406f917051b4bd5bd8fc0aa9df7d285b5dd7e5083ffc4bcd3f71d1f93b94c21fc1c8200f6c74aca1883baff2b80ac700
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Realm
|
2
|
+
|
3
|
+
Domain layer framework following Domain-driven/CQRS design principles.
|
4
|
+
|
5
|
+
[](https://buildkite.com/reevoo/realm)
|
6
|
+
|
7
|
+
## Service layers
|
8
|
+
|
9
|
+
We follow the standard MVC design pattern of Rails but giving the model layer more structure and guidance regarding where
|
10
|
+
to put your code. The model is split into domain layer (using our [Realm](https://github.com/reevoo/smart-mono/tree/master/gems/realm) library)
|
11
|
+
and persistence layer (using [ROM](https://rom-rb.org/) library). The individual components are explained in the following section.
|
12
|
+
|
13
|
+

|
14
|
+
|
15
|
+
Advanced components are shown in lighter color, those will be needed only later on as the service domain logic grows.
|
16
|
+
|
17
|
+
## Model layer components
|
18
|
+
|
19
|
+

|
20
|
+
|
21
|
+
Each service has one **domain** module which consists of multiple [**aggregate**](https://martinfowler.com/bliki/DDD_Aggregate.html) modules.
|
22
|
+
Aggregate is a cluster of domain objects that can be treated as a single unit. The only way for outer world to communicate
|
23
|
+
with aggregate is by **queries** and **commands**. Query exposes aggregate's internal state and command changes it.
|
24
|
+
The state of an aggregate is represented by tree of **entities** with one being the aggregate root and zero or more dependent
|
25
|
+
entities with *belongs_to* relation to the root entity. The state of an aggregate (entity tree) is persisted
|
26
|
+
and retrieved by **repository**. There is generally one repository per aggregate unless we split the read/write
|
27
|
+
(query/command) persistence model for that particular domain. The repository uses **relations** to access the database
|
28
|
+
tables. Each relation class represents one table.
|
29
|
+
|
30
|
+
|
31
|
+
## Where to put my code as it grows?
|
32
|
+
|
33
|
+
TODO
|
34
|
+
|
35
|
+
|
36
|
+
## Roadmap
|
37
|
+
|
38
|
+
- [ ] Support Ruby 3
|
39
|
+
- [ ] Make it work outside of Rails engines
|
40
|
+
- [ ] Support multiple persistence gateways in one runtime
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'rdoc/task'
|
10
|
+
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
13
|
+
rdoc.title = 'Realm'
|
14
|
+
rdoc.options << '--line-numbers'
|
15
|
+
rdoc.rdoc_files.include('README.md')
|
16
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'bundler/gem_tasks'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: realm-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- developers@reevoo.com
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '1.5'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: zeitwerk
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '2.4'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '2.4'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: pry-byebug
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,52 +164,19 @@ dependencies:
|
|
150
164
|
- - ">="
|
151
165
|
- !ruby/object:Gem::Version
|
152
166
|
version: '0'
|
153
|
-
description:
|
154
|
-
email:
|
167
|
+
description:
|
168
|
+
email:
|
155
169
|
executables: []
|
156
170
|
extensions: []
|
157
171
|
extra_rdoc_files: []
|
158
172
|
files:
|
159
|
-
-
|
160
|
-
-
|
161
|
-
|
162
|
-
- lib/realm/action_handler/result.rb
|
163
|
-
- lib/realm/builder.rb
|
164
|
-
- lib/realm/command_handler.rb
|
165
|
-
- lib/realm/config.rb
|
166
|
-
- lib/realm/container.rb
|
167
|
-
- lib/realm/context.rb
|
168
|
-
- lib/realm/dependency.rb
|
169
|
-
- lib/realm/dispatcher.rb
|
170
|
-
- lib/realm/domain_resolver.rb
|
171
|
-
- lib/realm/error.rb
|
172
|
-
- lib/realm/event.rb
|
173
|
-
- lib/realm/event_factory.rb
|
174
|
-
- lib/realm/event_handler.rb
|
175
|
-
- lib/realm/event_router.rb
|
176
|
-
- lib/realm/event_router/gateway.rb
|
177
|
-
- lib/realm/event_router/internal_loop_gateway.rb
|
178
|
-
- lib/realm/health_status.rb
|
179
|
-
- lib/realm/mixins/aggregate_member.rb
|
180
|
-
- lib/realm/mixins/context_injection.rb
|
181
|
-
- lib/realm/mixins/controller.rb
|
182
|
-
- lib/realm/mixins/decorator.rb
|
183
|
-
- lib/realm/mixins/dependency_injection.rb
|
184
|
-
- lib/realm/mixins/reactive.rb
|
185
|
-
- lib/realm/mixins/repository_helper.rb
|
186
|
-
- lib/realm/multi_worker.rb
|
187
|
-
- lib/realm/persistence.rb
|
188
|
-
- lib/realm/persistence/repository_query_handler_adapter.rb
|
189
|
-
- lib/realm/plugin.rb
|
190
|
-
- lib/realm/query_handler.rb
|
191
|
-
- lib/realm/runtime.rb
|
192
|
-
- lib/realm/runtime/session.rb
|
193
|
-
- lib/realm/types.rb
|
194
|
-
homepage:
|
173
|
+
- README.md
|
174
|
+
- Rakefile
|
175
|
+
homepage:
|
195
176
|
licenses:
|
196
177
|
- MIT
|
197
178
|
metadata: {}
|
198
|
-
post_install_message:
|
179
|
+
post_install_message:
|
199
180
|
rdoc_options: []
|
200
181
|
require_paths:
|
201
182
|
- lib
|
@@ -210,8 +191,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
210
191
|
- !ruby/object:Gem::Version
|
211
192
|
version: '0'
|
212
193
|
requirements: []
|
213
|
-
rubygems_version: 3.1.
|
214
|
-
signing_key:
|
194
|
+
rubygems_version: 3.1.4
|
195
|
+
signing_key:
|
215
196
|
specification_version: 4
|
216
197
|
summary: Domain layer framework following Domain-driven/CQRS design principles
|
217
198
|
test_files: []
|
data/lib/realm-core.rb
DELETED
data/lib/realm.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
Dir[File.join(File.dirname(__FILE__), 'realm', '**', '*.rb')].sort.each do |f|
|
4
|
-
require f
|
5
|
-
end
|
6
|
-
|
7
|
-
module Realm
|
8
|
-
class << self
|
9
|
-
# Setup realm in test/console
|
10
|
-
def setup(root_module, **options)
|
11
|
-
config = Realm::Config.new(root_module: root_module, **options)
|
12
|
-
Realm::Builder.setup(config)
|
13
|
-
end
|
14
|
-
|
15
|
-
# Bind realm in service/engine
|
16
|
-
def bind(root_module, **options)
|
17
|
-
setup(root_module, **options).tap do |builder|
|
18
|
-
root_module.define_singleton_method(:realm) { builder.runtime }
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/lib/realm/action_handler.rb
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'dry-validation'
|
4
|
-
require 'active_support/core_ext/module/delegation'
|
5
|
-
require 'realm/error'
|
6
|
-
require 'realm/mixins/context_injection'
|
7
|
-
require 'realm/mixins/repository_helper'
|
8
|
-
require 'realm/mixins/aggregate_member'
|
9
|
-
require_relative 'action_handler/result'
|
10
|
-
|
11
|
-
module Realm
|
12
|
-
class ActionHandler
|
13
|
-
extend Mixins::ContextInjection::ClassMethods
|
14
|
-
include Mixins::AggregateMember
|
15
|
-
include Mixins::RepositoryHelper
|
16
|
-
|
17
|
-
class << self
|
18
|
-
attr_reader :contracts
|
19
|
-
|
20
|
-
def call(action: :handle, params: {}, runtime: nil)
|
21
|
-
new(runtime: runtime).(action: action, params: params)
|
22
|
-
end
|
23
|
-
|
24
|
-
protected
|
25
|
-
|
26
|
-
def require_permission(*names)
|
27
|
-
# TODO: implement
|
28
|
-
end
|
29
|
-
|
30
|
-
def contract(&block)
|
31
|
-
@method_contract = Class.new(Dry::Validation::Contract, &block).new
|
32
|
-
end
|
33
|
-
|
34
|
-
def contract_schema(&block)
|
35
|
-
contract { schema(&block) }
|
36
|
-
end
|
37
|
-
|
38
|
-
def contract_params(&block)
|
39
|
-
contract { params(&block) }
|
40
|
-
end
|
41
|
-
|
42
|
-
def contract_json(&block)
|
43
|
-
contract { json(&block) }
|
44
|
-
end
|
45
|
-
|
46
|
-
def method_added(method_name)
|
47
|
-
super
|
48
|
-
return unless defined?(@method_contract)
|
49
|
-
|
50
|
-
@contracts ||= {}
|
51
|
-
@contracts[method_name] = @method_contract
|
52
|
-
remove_instance_variable(:@method_contract)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def initialize(runtime: nil)
|
57
|
-
@runtime = runtime
|
58
|
-
end
|
59
|
-
|
60
|
-
def call(action: :handle, params: {})
|
61
|
-
# TODO: check permissions
|
62
|
-
raise CannotHandleAction.new(self, action) unless respond_to?(action)
|
63
|
-
|
64
|
-
safe_params = validate(action, params.to_h)
|
65
|
-
send(action, **safe_params)
|
66
|
-
end
|
67
|
-
|
68
|
-
protected
|
69
|
-
|
70
|
-
delegate :context, to: :@runtime
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
def validate(action, params)
|
75
|
-
contract = self.class.contracts && self.class.contracts[action]
|
76
|
-
return params unless contract
|
77
|
-
|
78
|
-
result = contract.(params)
|
79
|
-
raise Realm::InvalidParams, result if result.failure?
|
80
|
-
|
81
|
-
result.to_h
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Realm
|
4
|
-
class ActionHandler
|
5
|
-
# Tuple of label and value
|
6
|
-
class Result < Array
|
7
|
-
def self.[](first, second = nil)
|
8
|
-
return new(first, second).freeze if first.is_a?(Symbol) || first.is_a?(Realm::Event)
|
9
|
-
|
10
|
-
new(second || :ok, first).freeze
|
11
|
-
end
|
12
|
-
|
13
|
-
def label
|
14
|
-
self[0]
|
15
|
-
end
|
16
|
-
|
17
|
-
def event
|
18
|
-
label if label.is_a?(Realm::Event)
|
19
|
-
end
|
20
|
-
|
21
|
-
def value
|
22
|
-
self[1]
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def initialize(label, value)
|
28
|
-
super([label, value])
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
data/lib/realm/builder.rb
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/string'
|
4
|
-
require 'realm/container'
|
5
|
-
require 'realm/runtime'
|
6
|
-
require 'realm/domain_resolver'
|
7
|
-
require 'realm/persistence'
|
8
|
-
require 'realm/dispatcher'
|
9
|
-
require 'realm/event_router'
|
10
|
-
require 'realm/plugin'
|
11
|
-
|
12
|
-
module Realm
|
13
|
-
class Builder
|
14
|
-
def self.setup(config)
|
15
|
-
new(config).setup
|
16
|
-
end
|
17
|
-
|
18
|
-
def initialize(config)
|
19
|
-
@config = config
|
20
|
-
end
|
21
|
-
|
22
|
-
def setup
|
23
|
-
logger.info("Setting up #{cfg.root_module} realm")
|
24
|
-
register_domain_resolver
|
25
|
-
register_event_router
|
26
|
-
register_runtime
|
27
|
-
register_logger
|
28
|
-
register_dependencies
|
29
|
-
setup_plugins
|
30
|
-
config_persistence
|
31
|
-
self
|
32
|
-
end
|
33
|
-
|
34
|
-
def runtime
|
35
|
-
@container.resolve(Runtime)
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def register_domain_resolver
|
41
|
-
container.register_factory(DomainResolver, constantize(cfg.domain_module))
|
42
|
-
end
|
43
|
-
|
44
|
-
def register_event_router
|
45
|
-
return if cfg.event_gateways.empty?
|
46
|
-
|
47
|
-
container.register_factory(EventRouter, cfg.event_gateways, prefix: cfg.prefix)
|
48
|
-
end
|
49
|
-
|
50
|
-
def register_runtime
|
51
|
-
container.register_factory(Runtime, container)
|
52
|
-
end
|
53
|
-
|
54
|
-
def register_logger
|
55
|
-
container.register(:logger, logger)
|
56
|
-
end
|
57
|
-
|
58
|
-
def register_dependencies
|
59
|
-
container.register_all(**cfg.dependencies)
|
60
|
-
end
|
61
|
-
|
62
|
-
def setup_plugins
|
63
|
-
Plugin.descendants.each do |plugin|
|
64
|
-
plugin.setup(cfg, container) if cfg.plugins.include?(plugin.plugin_name)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def config_persistence
|
69
|
-
return unless cfg.persistence_gateway.present?
|
70
|
-
|
71
|
-
Persistence.setup(container, cfg.persistence_gateway[:repositories])
|
72
|
-
end
|
73
|
-
|
74
|
-
def constantize(*parts)
|
75
|
-
return parts[0] unless parts[0].is_a?(String)
|
76
|
-
|
77
|
-
parts.join('::').safe_constantize
|
78
|
-
end
|
79
|
-
|
80
|
-
def cfg
|
81
|
-
@config
|
82
|
-
end
|
83
|
-
|
84
|
-
def container
|
85
|
-
@container ||= Container.new
|
86
|
-
end
|
87
|
-
|
88
|
-
def logger
|
89
|
-
@logger ||= cfg.logger || (defined?(Rails) && Rails.logger) ||
|
90
|
-
Logger.new($stdout, level: ENV.fetch('LOG_LEVEL', :info).to_sym)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/module/delegation'
|
4
|
-
require 'active_support/core_ext/string'
|
5
|
-
require 'realm/action_handler'
|
6
|
-
require 'realm/mixins/reactive'
|
7
|
-
|
8
|
-
module Realm
|
9
|
-
class CommandHandler < Realm::ActionHandler
|
10
|
-
include Mixins::Reactive
|
11
|
-
|
12
|
-
def call(*)
|
13
|
-
gateway = context[:rom]&.gateways&.dig(:default)
|
14
|
-
gateway ? gateway.transaction { super } : super
|
15
|
-
end
|
16
|
-
|
17
|
-
protected
|
18
|
-
|
19
|
-
def result(first, second = nil)
|
20
|
-
Result[first, second]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|