realm-core 0.7.0 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.
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: []