realm-core 0.7.0 → 0.7.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f61dae355ea08d78da40bc227540ce47635d09ac0f8645d3f70e1e53201ff54
4
- data.tar.gz: 57bfe266b33d2f7744b87af84b14a2bd0d7a3c25c0bfc6b452457488067ad181
3
+ metadata.gz: 8e6f3990f8dc36366899e3a8bbf1835bf6cf0bb880bcf13333f394b40d1075e3
4
+ data.tar.gz: a03e2bb0fa656cfaada1364db1d8af4c222cbaff8cec5ffd0223629b40e11bc2
5
5
  SHA512:
6
- metadata.gz: 3568eca1b26cd974a6d860e233cb50d4911e49bd7f61f4d6c43d865e78cbded0d48dd40e6331fa8d46ce3eb8906a7093c797ce340e16e33c4fad441085199c72
7
- data.tar.gz: cca39336c0d199d46254e15293439b9e81f401b8e4a586f68eb90658a5e027888f4bce1911dad21dbbd6fb2a6c4c68e4380d47935d1492c962e84a092496f8de
6
+ metadata.gz: 627b95689b8a4d51fb15a8665dd65be88974380c00a168f1121ae5248738140eadd82f3735ccaa0391fb33274952a9e1fe83819813b7312921b9adeb85956816
7
+ data.tar.gz: ed1a34e594acb1e7f3ef3d644aecad58af6b9fdc1b436fb3ba793cdbdc131affdecf26e832b9d2997ab45501dba91bda950735e3e85bbd518cf5e7eaaea2ce7e
data/lib/realm-core.rb CHANGED
@@ -2,5 +2,10 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'realm'
5
+ require 'zeitwerk'
6
+
7
+ loader = Zeitwerk::Loader.for_gem
8
+ loader.ignore(__FILE__)
9
+ loader.setup
5
10
 
6
11
  # rubocop:enable Naming/FileName
data/lib/realm.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Dir[File.join(File.dirname(__FILE__), 'realm', '**', '*.rb')].sort.each do |f|
4
- require f
5
- end
3
+ require 'active_support/all'
4
+ require 'dry/core/constants'
6
5
 
7
6
  module Realm
8
7
  class << self
@@ -18,5 +17,13 @@ module Realm
18
17
  root_module.define_singleton_method(:realm) { builder.runtime }
19
18
  end
20
19
  end
20
+
21
+ # port the construction method from Dry::Struct as it's not inherited
22
+ def Struct(attributes = Dry::Core::Constants::EMPTY_HASH, &block) # rubocop:disable Naming/MethodName
23
+ Class.new(Struct) do
24
+ attributes.each { |a, type| attribute a, type }
25
+ module_eval(&block) if block
26
+ end
27
+ end
21
28
  end
22
29
  end
@@ -1,12 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
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
4
 
11
5
  module Realm
12
6
  class ActionHandler
@@ -28,21 +22,25 @@ module Realm
28
22
  end
29
23
 
30
24
  def contract(&block)
31
- @method_contract = Class.new(Dry::Validation::Contract, &block).new
25
+ @method_contract = Class.new(Realm::Contract, &block).new
32
26
  end
33
27
 
34
- def contract_schema(&block)
35
- contract { schema(&block) }
28
+ def contract_schema(...)
29
+ contract { schema(...) }
36
30
  end
37
31
 
38
- def contract_params(&block)
39
- contract { params(&block) }
32
+ def contract_params(...)
33
+ contract { params(...) }
40
34
  end
41
35
 
42
- def contract_json(&block)
43
- contract { json(&block) }
36
+ def contract_json(...)
37
+ contract { json(...) }
44
38
  end
45
39
 
40
+ alias schema_contract contract_schema
41
+ alias params_contract contract_params
42
+ alias json_contract contract_json
43
+
46
44
  def method_added(method_name)
47
45
  super
48
46
  return unless defined?(@method_contract)
data/lib/realm/builder.rb CHANGED
@@ -1,14 +1,5 @@
1
1
  # frozen_string_literal: true
2
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
3
  module Realm
13
4
  class Builder
14
5
  def self.setup(config)
@@ -1,10 +1,5 @@
1
1
  # frozen_string_literal: true
2
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
3
  module Realm
9
4
  class CommandHandler < Realm::ActionHandler
10
5
  include Mixins::Reactive
data/lib/realm/config.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/core_ext/string'
4
3
  require 'dry-initializer'
5
4
 
6
5
  module Realm
@@ -1,9 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'dry-container'
4
- require 'active_support/core_ext/string'
5
- require 'active_support/core_ext/object/try'
6
- require 'realm/error'
7
4
 
8
5
  module Realm
9
6
  class Container
data/lib/realm/context.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'realm/container'
4
-
5
3
  module Realm
6
4
  class Context
7
5
  include Enumerable
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-validation'
4
+
5
+ module Realm
6
+ class Contract < Dry::Validation::Contract
7
+ class NotConvertibleToSchema < Realm::Error
8
+ def initialize(thing)
9
+ super("Not convertible to schema: #{thing}")
10
+ end
11
+ end
12
+
13
+ class << self
14
+ def schema(*external_schemas, **attributes, &block)
15
+ super(*sanitize_schemas(external_schemas, attributes), &block)
16
+ end
17
+
18
+ def params(*external_schemas, **attributes, &block)
19
+ super(*sanitize_schemas(external_schemas, attributes), &block)
20
+ end
21
+
22
+ def json(*external_schemas, **attributes, &block)
23
+ super(*sanitize_schemas(external_schemas, attributes), &block)
24
+ end
25
+
26
+ private
27
+
28
+ def sanitize_schemas(things, attributes, type = :schema)
29
+ things << Realm.Struct(attributes) if attributes.present?
30
+ things.map { |thing| convert_to_schema(thing, type) }
31
+ end
32
+
33
+ def convert_to_schema(thing, type)
34
+ return thing if thing.is_a? Dry::Schema::Processor # already a schema
35
+
36
+ raise NotConvertibleToSchema, thing unless thing.respond_to?(:to_dry_schema)
37
+
38
+ thing.to_dry_schema(type: type)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/core_ext/string'
4
-
5
3
  module Realm
6
4
  class Dependency
7
5
  attr_reader :dependable, :name
@@ -1,13 +1,5 @@
1
1
  # frozen_string_literal: true
2
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
3
  module Realm
12
4
  class Dispatcher
13
5
  include Mixins::DependencyInjection
@@ -1,11 +1,5 @@
1
1
  # frozen_string_literal: true
2
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
3
  module Realm
10
4
  class DomainResolver
11
5
  DOMAIN_CLASS_TYPES = [CommandHandler, QueryHandler, EventHandler].freeze
@@ -21,7 +15,7 @@ module Realm
21
15
  handlers = @index[type]
22
16
  return [handlers[identifier], :handle] if handlers.key?(identifier)
23
17
 
24
- # The last part of the identifier can action method name inside the handler
18
+ # The last part of the identifier can be action method name inside the handler
25
19
  parts = identifier.split('.')
26
20
  handler_part = parts[..-2].join('.')
27
21
  action = parts[-1]
data/lib/realm/error.rb CHANGED
@@ -59,6 +59,4 @@ module Realm
59
59
  @validation_result.errors(full: true).to_h
60
60
  end
61
61
  end
62
-
63
- class UniqueConstraintError < Error; end
64
62
  end
data/lib/realm/event.rb CHANGED
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'securerandom'
4
- require 'active_support/core_ext/hash'
5
- require 'active_support/core_ext/string'
4
+ require 'dry/core/constants'
6
5
  require 'dry-struct'
7
- require 'realm/types'
8
6
 
9
7
  module Realm
10
8
  class Event < Dry::Struct
@@ -34,14 +32,15 @@ module Realm
34
32
  super({ head: head }.merge(body.empty? ? {} : { body: body }))
35
33
  end
36
34
 
37
- def type
35
+ def type(value = :not_provided)
36
+ @type = value unless value == :not_provided
38
37
  @type ||= name.demodulize.sub('Event', '').underscore
39
38
  end
40
39
 
41
40
  protected
42
41
 
43
- def body_struct(&block)
44
- attribute(:body, &block)
42
+ def body_struct(type = Dry::Core::Constants::Undefined, &block)
43
+ attribute(:body, type, &block)
45
44
  end
46
45
  end
47
46
 
@@ -1,12 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'realm/error'
4
- require 'realm/event'
5
-
6
3
  module Realm
7
4
  class EventFactory
8
5
  def initialize(events_module)
9
6
  @events_module = events_module
7
+ @event_class_map = collect_event_classes(events_module)
10
8
  end
11
9
 
12
10
  def create_event(event_type, correlate: nil, cause: nil, **attributes)
@@ -19,15 +17,24 @@ module Realm
19
17
  def event_class_for(event_type)
20
18
  return event_type if event_type.respond_to?(:new)
21
19
 
22
- class_name = "#{@events_module}::#{event_type.to_s.camelize}"
23
- klass = class_name.safe_constantize || "#{class_name}Event".safe_constantize
24
- return klass if klass
25
-
26
- raise EventClassMissing.new(event_type, @events_module)
20
+ @event_class_map.fetch(event_type.to_s) do
21
+ raise EventClassMissing.new(event_type, @events_module)
22
+ end
27
23
  end
28
24
 
29
25
  private
30
26
 
27
+ def collect_event_classes(root_module)
28
+ root_module_str = root_module.to_s
29
+ root_module.constants.each_with_object({}) do |const_sym, all|
30
+ const = root_module.const_get(const_sym)
31
+ next unless const.is_a?(Module) && const.to_s.start_with?(root_module_str)
32
+
33
+ all[const.type] = const if const < Event
34
+ all.merge!(collect_event_classes(const))
35
+ end
36
+ end
37
+
31
38
  def enhance_head(head, correlate:, cause:)
32
39
  head[:correlation_id] = correlate.head.correlation_id if correlate
33
40
  if cause.is_a?(Event)
@@ -1,12 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/core_ext/string'
4
- require 'realm/error'
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
3
  module Realm
11
4
  class EventHandler
12
5
  extend Mixins::ContextInjection::ClassMethods
@@ -38,12 +31,11 @@ module Realm
38
31
  new(runtime: runtime).(event)
39
32
  end
40
33
 
41
- def identifier(value = :undefined)
42
- if value == :undefined
43
- defined?(@identifier) ? @identifier : name.gsub(/(Domain|EventHandlers?)/, '').underscore.gsub(%r{/+}, '-')
44
- else
45
- @identifier = value
46
- end
34
+ def identifier(value = :not_provided)
35
+ @identifier = value unless value == :not_provided
36
+ return @identifier if defined?(@identifier)
37
+
38
+ @identifier = name.gsub(/(Domain|(::)?(Event)?Handlers?)/, '').underscore.gsub(%r{/+}, '-')
47
39
  end
48
40
 
49
41
  def event_types
@@ -84,7 +76,7 @@ module Realm
84
76
  def call(event)
85
77
  event_to_methods(event).each do |method_name|
86
78
  send(method_name, event)
87
- rescue Realm::UniqueConstraintError => e
79
+ rescue Realm::Persistence::Conflict => e
88
80
  context[:logger]&.warn(e.full_message)
89
81
  end
90
82
  end
@@ -1,14 +1,5 @@
1
1
  # frozen_string_literal: true
2
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
3
  module Realm
13
4
  class EventRouter
14
5
  include Mixins::DependencyInjection
@@ -31,7 +22,7 @@ module Realm
31
22
  end
32
23
 
33
24
  def trigger(identifier, attributes = {})
34
- namespace, event_type = identifier.to_s.include?('.') ? identifier.split('.') : [nil, identifier]
25
+ namespace, event_type = identifier.to_s.include?('/') ? identifier.split('/') : [nil, identifier]
35
26
  gateway_for(namespace).trigger(event_type, attributes)
36
27
  end
37
28
 
@@ -14,6 +14,7 @@ module Realm
14
14
  end
15
15
 
16
16
  def register(handler_class)
17
+ # TODO: validate event_types for existence of matching class
17
18
  handler_class.event_types.each do |event_type|
18
19
  add_listener(event_type, handler_class.bind_runtime(@runtime))
19
20
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative './gateway'
4
-
5
3
  module Realm
6
4
  class EventRouter
7
5
  class InternalLoopGateway < Gateway
@@ -17,7 +15,7 @@ module Realm
17
15
  end
18
16
 
19
17
  def add_listener(event_type, listener)
20
- (@listener_map[event_type] ||= []) << listener
18
+ (@listener_map[event_type.to_sym] ||= []) << listener
21
19
  end
22
20
 
23
21
  def trigger(event_type, attributes = {})
@@ -39,7 +37,7 @@ module Realm
39
37
  private
40
38
 
41
39
  def find_listeners(event_type)
42
- @listener_map.fetch_values(event_type, :any) { [] }.flatten
40
+ @listener_map.fetch_values(event_type.to_sym, :any) { [] }.flatten
43
41
  end
44
42
 
45
43
  def gateways
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/core_ext/object/blank'
4
-
5
3
  module Realm
6
4
  class HealthStatus
7
5
  CODES = %i[green yellow red].freeze
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'realm/error'
4
-
5
3
  module Realm
6
4
  module Mixins
7
5
  module ContextInjection
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/core_ext/module/introspection'
4
- require 'active_support/core_ext/class/attribute'
5
-
6
3
  module Realm
7
4
  module Mixins
8
5
  module Controller
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'realm/dependency'
4
-
5
3
  module Realm
6
4
  module Mixins
7
5
  module DependencyInjection
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'realm/error'
4
-
5
3
  module Realm
6
4
  module Mixins
7
5
  module Reactive
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'realm/error'
4
-
5
3
  module Realm
6
4
  module Mixins
7
5
  module RepositoryHelper
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/core_ext/string'
4
- require 'realm/error'
5
-
6
3
  module Realm
7
4
  class Persistence
8
5
  class InvalidPersistanceType < Realm::Error; end
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'realm/persistence'
4
- require 'realm/error'
5
-
6
3
  module Realm
7
4
  class Persistence
8
5
  class QueryCannotModifyState < Realm::Error; end
data/lib/realm/plugin.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/core_ext/class'
4
- require 'active_support/core_ext/string'
5
-
6
3
  module Realm
7
4
  class Plugin
8
5
  class << self
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'realm/action_handler'
4
-
5
3
  module Realm
6
4
  class QueryHandler < Realm::ActionHandler
7
5
  end
data/lib/realm/runtime.rb CHANGED
@@ -1,15 +1,5 @@
1
1
  # frozen_string_literal: true
2
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
3
  module Realm
14
4
  class Runtime
15
5
  delegate :query, :run, :run_as_job, :wait_for_jobs, to: :dispatcher
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'realm/dispatcher'
4
-
5
3
  module Realm
6
4
  class Runtime
7
5
  class Session
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-struct'
4
+ require 'dry-schema'
5
+
6
+ module Realm
7
+ class Struct < Dry::Struct
8
+ class << self
9
+ def to_dry_schema(type: :schema) # rubocop:disable Metrics/AbcSize
10
+ keys = schema.type.keys
11
+
12
+ Dry::Schema.send(schema_type_to_method(type)) do
13
+ keys.each do |key|
14
+ param = key.required? ? required(key.name) : optional(key.name)
15
+
16
+ if key.type.constructor_type == Dry::Types::Array::Constructor # array type
17
+ member = key.type.member
18
+ param.array(member.respond_to?(:to_dry_schema) ? member.to_dry_schema(type: type) : member)
19
+ elsif key.respond_to?(:to_dry_schema) # realm struct
20
+ param.hash(key.to_dry_schema(type: type))
21
+ else
22
+ param.send(key.required? ? :filled : :maybe, key.type)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def merge(attributes)
29
+ clone.attributes(attributes)
30
+ end
31
+
32
+ private
33
+
34
+ def schema_type_to_method(type)
35
+ case type
36
+ when :schema
37
+ :define
38
+ when :params
39
+ :Params
40
+ when :json
41
+ :JSON
42
+ else
43
+ raise "Not supported schema type #{type}"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
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.0
4
+ version: 0.7.5
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-06-21 00:00:00.000000000 Z
11
+ date: 2021-07-15 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,8 +164,8 @@ 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: []
@@ -165,6 +179,7 @@ files:
165
179
  - lib/realm/config.rb
166
180
  - lib/realm/container.rb
167
181
  - lib/realm/context.rb
182
+ - lib/realm/contract.rb
168
183
  - lib/realm/dependency.rb
169
184
  - lib/realm/dispatcher.rb
170
185
  - lib/realm/domain_resolver.rb
@@ -190,12 +205,13 @@ files:
190
205
  - lib/realm/query_handler.rb
191
206
  - lib/realm/runtime.rb
192
207
  - lib/realm/runtime/session.rb
208
+ - lib/realm/struct.rb
193
209
  - lib/realm/types.rb
194
- homepage:
210
+ homepage:
195
211
  licenses:
196
212
  - MIT
197
213
  metadata: {}
198
- post_install_message:
214
+ post_install_message:
199
215
  rdoc_options: []
200
216
  require_paths:
201
217
  - lib
@@ -210,8 +226,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
226
  - !ruby/object:Gem::Version
211
227
  version: '0'
212
228
  requirements: []
213
- rubygems_version: 3.1.6
214
- signing_key:
229
+ rubygems_version: 3.1.4
230
+ signing_key:
215
231
  specification_version: 4
216
232
  summary: Domain layer framework following Domain-driven/CQRS design principles
217
233
  test_files: []