midnight-business_logic 0.0.1
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 +7 -0
- data/lib/midnight/business_logic.rb +19 -0
- data/lib/midnight/business_logic/aggregate_root.rb +46 -0
- data/lib/midnight/business_logic/event.rb +47 -0
- data/lib/midnight/business_logic/event_dispatcher.rb +69 -0
- data/lib/midnight/business_logic/version.rb +5 -0
- data/lib/midnight/commons/concurrent_write_error.rb +8 -0
- data/lib/midnight/commons/constants.rb +5 -0
- metadata +64 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 24cfcc468f4e7e48f77e50e2728017a106ea7a07703aa11d939781766eb5ad61
|
|
4
|
+
data.tar.gz: 36e4bcb84ec676b5cdb6ddd3523ec08d43630573bc9bf9602315c01db1694f75
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0ab18cc817a8aaf3d1bbc3d4d1b7bf389de5bc91f1bbb33d673571c1402c7503b1b636316e8c846770f60d8b7a7ce8486d1fe9bb47683c282b7c94bb3006b026
|
|
7
|
+
data.tar.gz: fa3cdba82a930e1759665d7e13f287001f589fbdbcc84fed14625007fba5c289dc4270c4a56d70a620de2d7a6580d90c8796c5eb4e1e2a9c6a39632b5604dabc
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'active_support/dependencies/autoload'
|
|
2
|
+
require_relative 'business_logic/version'
|
|
3
|
+
|
|
4
|
+
module Midnight
|
|
5
|
+
module Commons
|
|
6
|
+
extend ::ActiveSupport::Autoload
|
|
7
|
+
|
|
8
|
+
autoload :ConcurrentWriteError
|
|
9
|
+
autoload :NULL_EVENT_HANDLER, 'midnight/commons/constants'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module BusinessLogic
|
|
13
|
+
extend ::ActiveSupport::Autoload
|
|
14
|
+
|
|
15
|
+
autoload :AggregateRoot
|
|
16
|
+
autoload :Event
|
|
17
|
+
autoload :EventDispatcher
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
module Midnight
|
|
4
|
+
module BusinessLogic
|
|
5
|
+
module AggregateRoot
|
|
6
|
+
class UnknownCommand < ArgumentError
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
extend ::ActiveSupport::Concern
|
|
10
|
+
|
|
11
|
+
def dispatch(_command)
|
|
12
|
+
raise UnknownCommand
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def state
|
|
16
|
+
@state ||= {}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def pending_events
|
|
20
|
+
@pending_events ||= []
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class_methods do
|
|
24
|
+
attr_accessor :_event_handlers
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def on(event_class, &block)
|
|
29
|
+
self._event_handlers ||= {}
|
|
30
|
+
self._event_handlers[event_class] = block
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def apply(*events)
|
|
37
|
+
handlers = self.class._event_handlers || {}
|
|
38
|
+
events.each do |event|
|
|
39
|
+
handler = handlers[event.class]
|
|
40
|
+
instance_exec(event, &handler) if handler
|
|
41
|
+
pending_events << event
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'time'
|
|
2
|
+
require 'active_support/core_ext/time'
|
|
3
|
+
|
|
4
|
+
module Midnight
|
|
5
|
+
module BusinessLogic
|
|
6
|
+
class Event
|
|
7
|
+
class SchemaViolation < ArgumentError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
DEFAULT_METADATA_GENERATOR = lambda do
|
|
11
|
+
{
|
|
12
|
+
occurred_at: ::Time.current.iso8601(6)
|
|
13
|
+
}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(data: {}, metadata: nil)
|
|
17
|
+
@data = data
|
|
18
|
+
@metadata = metadata || DEFAULT_METADATA_GENERATOR.call
|
|
19
|
+
freeze
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
attr_reader :data, :metadata
|
|
23
|
+
|
|
24
|
+
class << self
|
|
25
|
+
def strict(data: {}, metadata: nil)
|
|
26
|
+
ensure_schema(data)
|
|
27
|
+
new(
|
|
28
|
+
data: data,
|
|
29
|
+
metadata: metadata
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def ensure_schema(_data)
|
|
36
|
+
raise NotImplementedError
|
|
37
|
+
# example
|
|
38
|
+
# @data_schema ||= ::Dry::Schema.Params do
|
|
39
|
+
# required(:example_field).filled(:string)
|
|
40
|
+
# end
|
|
41
|
+
# result = @data_schema.call(data)
|
|
42
|
+
# raise SchemaViolation unless result.success?
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
|
2
|
+
|
|
3
|
+
module Midnight
|
|
4
|
+
module BusinessLogic
|
|
5
|
+
class EventDispatcher
|
|
6
|
+
class InvalidHandlerSupplied < ArgumentError
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize(handlers_map = {})
|
|
10
|
+
handlers_map.each do |_event_class, handler_list|
|
|
11
|
+
handler_list.each do |handler|
|
|
12
|
+
raise InvalidHandlerSupplied unless handler.respond_to?(:call)
|
|
13
|
+
# correct construction example:
|
|
14
|
+
# EventDispatcher.new(SomeEvent => [
|
|
15
|
+
# method(:puts)
|
|
16
|
+
# ])
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
@_handlers_map = handlers_map
|
|
20
|
+
freeze
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def once(event)
|
|
24
|
+
handler_list = @_handlers_map[event.class]
|
|
25
|
+
unless handler_list.blank?
|
|
26
|
+
handler_list.each do |handler|
|
|
27
|
+
handler.call(event)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def batch(events)
|
|
33
|
+
events.each(&method(:once))
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class CompositeEventDispatcher # quack like EventDispatcher
|
|
38
|
+
def initialize(*dispatchers)
|
|
39
|
+
@_dispatchers = dispatchers
|
|
40
|
+
freeze
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def once(event)
|
|
44
|
+
@_dispatchers.each do |dispatcher|
|
|
45
|
+
dispatcher.once(event)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def batch(events)
|
|
50
|
+
events.each(&method(:once))
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
private_constant :CompositeEventDispatcher
|
|
54
|
+
|
|
55
|
+
class EventDispatcher
|
|
56
|
+
class InvalidDispatcherSupplied < ArgumentError;
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class << self
|
|
60
|
+
def merge(*dispatchers)
|
|
61
|
+
raise InvalidDispatcherSupplied unless dispatchers.all? do |dispatcher|
|
|
62
|
+
dispatcher.respond_to?(:once)
|
|
63
|
+
end
|
|
64
|
+
CompositeEventDispatcher.new(*dispatchers)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: midnight-business_logic
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Sarun Rattanasiri
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2019-08-04 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: activesupport
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
description: Midnight::BusinessLogic is a toolkit for writing clean and robust business
|
|
28
|
+
logics agnostic to frameworks, user interfaces, and data storage. Make the business
|
|
29
|
+
logic fully testable and provides isolation from external side effects.
|
|
30
|
+
email: midnight_w@gmx.tw
|
|
31
|
+
executables: []
|
|
32
|
+
extensions: []
|
|
33
|
+
extra_rdoc_files: []
|
|
34
|
+
files:
|
|
35
|
+
- lib/midnight/business_logic.rb
|
|
36
|
+
- lib/midnight/business_logic/aggregate_root.rb
|
|
37
|
+
- lib/midnight/business_logic/event.rb
|
|
38
|
+
- lib/midnight/business_logic/event_dispatcher.rb
|
|
39
|
+
- lib/midnight/business_logic/version.rb
|
|
40
|
+
- lib/midnight/commons/concurrent_write_error.rb
|
|
41
|
+
- lib/midnight/commons/constants.rb
|
|
42
|
+
homepage: https://gitlab.com/slime-systems/midnight-enterprise-toolkit/tree/master/midnight-business_logic
|
|
43
|
+
licenses: []
|
|
44
|
+
metadata: {}
|
|
45
|
+
post_install_message:
|
|
46
|
+
rdoc_options: []
|
|
47
|
+
require_paths:
|
|
48
|
+
- lib
|
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '0'
|
|
59
|
+
requirements: []
|
|
60
|
+
rubygems_version: 3.0.3
|
|
61
|
+
signing_key:
|
|
62
|
+
specification_version: 4
|
|
63
|
+
summary: A toolkit for writing enterprise business logic
|
|
64
|
+
test_files: []
|