lowevent 0.8.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/events/hidden_event.rb +36 -0
- data/lib/events/render_event.rb +12 -0
- data/lib/events/request_event.rb +17 -0
- data/lib/events/response_event.rb +19 -0
- data/lib/events/status_event.rb +25 -0
- data/lib/factories/response_factory.rb +18 -0
- data/lib/interfaces/definable.rb +17 -0
- data/lib/interfaces/event.rb +89 -0
- data/lib/lowevent.rb +17 -0
- data/lib/pool/branch_event.rb +18 -0
- data/lib/pool/event_pool.rb +50 -0
- data/lib/pool/event_tree.rb +35 -0
- data/lib/support/pool_hash.rb +23 -0
- data/lib/support/value_object.rb +11 -0
- data/lib/version.rb +5 -0
- metadata +112 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 58811c1dffb8954d8dd1ef1e40e322ffb2b6ea6a9d824e1205c05d1803e6c565
|
|
4
|
+
data.tar.gz: 12afa112f58ad6f0aa1425572db2f8d38a32416d9f48d58be3bf172a0e7d2b40
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: da3ccf1f9f03e42f3172237b1c70196485d512146ad4e0d5a4d7e1aa27d6357fbcc381285115d79c241052f8dec7bbe3d52d97d786f00d821e5e5811aaa4b4de
|
|
7
|
+
data.tar.gz: 6d03f85b9cc65fe1cecbb0a9254d5a31a636a8e85b557f37fe20814f70b4c4095c7c182037692cf3c3b16c15cdbecbfc5b2b06c3196bc2f6437084e9782dad9b
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lowtype'
|
|
4
|
+
|
|
5
|
+
module Low
|
|
6
|
+
module Events
|
|
7
|
+
# An event that happens on event tree branching and isn't added to the event tree/sequence.
|
|
8
|
+
class HiddenEvent
|
|
9
|
+
include LowType
|
|
10
|
+
|
|
11
|
+
attr_reader :key, :action, :created_at
|
|
12
|
+
|
|
13
|
+
def initialize(key:, action: nil)
|
|
14
|
+
@key = key
|
|
15
|
+
@action = action
|
|
16
|
+
@created_at = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def trigger
|
|
20
|
+
event_tree = branch
|
|
21
|
+
key = Observers::Keys[@key]
|
|
22
|
+
key.trigger(event: self) { restore_level(event_tree:) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class << self
|
|
26
|
+
def trigger(**kwargs)
|
|
27
|
+
new(**kwargs).trigger
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def inherited(child)
|
|
31
|
+
child.include LowType
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Low
|
|
4
|
+
module Events
|
|
5
|
+
RenderEvent = Data.define(:action, :props) do
|
|
6
|
+
# TODO: Duplicate props when used in a parallelized situation (antlers: "<{ :parallelize }>")
|
|
7
|
+
def initialize(action: :render, props: {})
|
|
8
|
+
super
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../interfaces/event'
|
|
4
|
+
|
|
5
|
+
module Low
|
|
6
|
+
module Events
|
|
7
|
+
class RequestEvent < Event
|
|
8
|
+
attr_reader :request
|
|
9
|
+
|
|
10
|
+
def initialize(request:, action: :request)
|
|
11
|
+
super(key: self.class, action:)
|
|
12
|
+
|
|
13
|
+
@request = request
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'protocol/http'
|
|
4
|
+
require_relative '../interfaces/event'
|
|
5
|
+
|
|
6
|
+
module Low
|
|
7
|
+
module Events
|
|
8
|
+
class ResponseEvent < Event
|
|
9
|
+
attr_reader :response
|
|
10
|
+
|
|
11
|
+
# TODO: Type: "response: Protocol::HTTP::Response"
|
|
12
|
+
def initialize(response: nil)
|
|
13
|
+
super(key: self.class, action: :respond)
|
|
14
|
+
|
|
15
|
+
@response = response
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../interfaces/event'
|
|
4
|
+
|
|
5
|
+
module Low
|
|
6
|
+
module Events
|
|
7
|
+
class StatusEvent < Event
|
|
8
|
+
attr_reader :status, :request
|
|
9
|
+
|
|
10
|
+
def initialize(status:, request:, key: nil, action: :render)
|
|
11
|
+
super(key: key || status, action:)
|
|
12
|
+
|
|
13
|
+
@status = status
|
|
14
|
+
@request = request
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Status is a complex type that can be represented by both "Status" generically and "Status[:code]" specifically.
|
|
18
|
+
class << self
|
|
19
|
+
def trigger(status:, **kwargs)
|
|
20
|
+
new(status:, **kwargs).trigger || new(status:, key: Status, **kwargs).trigger
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'protocol/http'
|
|
4
|
+
|
|
5
|
+
module Low
|
|
6
|
+
module Events
|
|
7
|
+
class ResponseFactory
|
|
8
|
+
class << self
|
|
9
|
+
def response(body:)
|
|
10
|
+
headers = Protocol::HTTP::Headers.new(['content-type', 'text/html'])
|
|
11
|
+
body = Protocol::HTTP::Body::Buffered.wrap(body.strip)
|
|
12
|
+
|
|
13
|
+
Protocol::HTTP::Response.new('http/1.1', 200, headers, body)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lowtype'
|
|
4
|
+
require 'observers'
|
|
5
|
+
require_relative 'definable'
|
|
6
|
+
require_relative '../support/value_object'
|
|
7
|
+
|
|
8
|
+
module Low
|
|
9
|
+
# An event represents what is currently happening; the past, present and future.
|
|
10
|
+
#
|
|
11
|
+
# They are action-driven, representing inputs and outputs in a linear pipeline-like flow,
|
|
12
|
+
# which end up as children of the event... which is why events are mutable (except for RenderEvent).
|
|
13
|
+
# They are one-to-many with a return value.
|
|
14
|
+
#
|
|
15
|
+
# Integrations:
|
|
16
|
+
# - Observers for observer pattern which we wrap in an event-centric API
|
|
17
|
+
# - EventPool for a tree of events and their child events (defined in this gem)
|
|
18
|
+
# - LowState for state machines to trigger multiple ordered actions [UNLRELEASED]
|
|
19
|
+
class Event
|
|
20
|
+
include LowType
|
|
21
|
+
include Observers
|
|
22
|
+
include Events::Definable
|
|
23
|
+
include Support::ValueObject
|
|
24
|
+
|
|
25
|
+
attr_reader :key, :action, :actions, :created_at
|
|
26
|
+
attr_accessor :children
|
|
27
|
+
|
|
28
|
+
# Subclass provides a key such as "self.class".
|
|
29
|
+
# Subclass defines default action or actions, but not both.
|
|
30
|
+
def initialize(key:, action: nil, actions: [], children: [])
|
|
31
|
+
@key = key
|
|
32
|
+
@action = action
|
|
33
|
+
@actions = actions
|
|
34
|
+
@children = children
|
|
35
|
+
|
|
36
|
+
@created_at = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def trigger
|
|
40
|
+
event_tree = branch
|
|
41
|
+
key = Observers::Keys[@key]
|
|
42
|
+
key.trigger(event: self) { restore_level(event_tree:) }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def take
|
|
46
|
+
event_tree = branch
|
|
47
|
+
key = Observers::Keys[@key]
|
|
48
|
+
key.take(event: self) { restore_level(event_tree:) }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def branch
|
|
52
|
+
event_tree = Providers['low.event.pool'].current_event_tree(event: self)
|
|
53
|
+
event_tree.branch(event: self)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def restore_level(event_tree:)
|
|
59
|
+
event_tree.current_event = self if event_tree.respond_to?(:current_event)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
class << self
|
|
63
|
+
def trigger(**kwargs) = new(**kwargs).trigger
|
|
64
|
+
def take(**kwargs) = new(**kwargs).take
|
|
65
|
+
|
|
66
|
+
def inherited(child)
|
|
67
|
+
child.include LowType
|
|
68
|
+
increase_count
|
|
69
|
+
add_event(child)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def count
|
|
73
|
+
@count ||= 0
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def increase_count
|
|
77
|
+
@count = count + 1
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def events
|
|
81
|
+
@events ||= []
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def add_event(event)
|
|
85
|
+
events << event
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
data/lib/lowevent.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'providers'
|
|
4
|
+
|
|
5
|
+
require_relative 'events/render_event'
|
|
6
|
+
require_relative 'events/request_event'
|
|
7
|
+
require_relative 'events/response_event'
|
|
8
|
+
require_relative 'events/status_event'
|
|
9
|
+
require_relative 'factories/response_factory' # TODO: Find out who's using this and require it there.
|
|
10
|
+
require_relative 'interfaces/event'
|
|
11
|
+
require_relative 'pool/event_pool'
|
|
12
|
+
|
|
13
|
+
Providers.define('low.event.pool') do
|
|
14
|
+
Low::Events::EventPool.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
LowEvent = Low::Event
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../events/hidden_event'
|
|
4
|
+
|
|
5
|
+
module Low
|
|
6
|
+
module Events
|
|
7
|
+
class BranchEvent < HiddenEvent
|
|
8
|
+
attr_reader :event_tree, :event
|
|
9
|
+
|
|
10
|
+
def initialize(event_tree:, event:)
|
|
11
|
+
super(key: BranchEvent, action: :branch)
|
|
12
|
+
|
|
13
|
+
@event_tree = event_tree
|
|
14
|
+
@event = event
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'observers'
|
|
4
|
+
|
|
5
|
+
require_relative '../events/request_event'
|
|
6
|
+
require_relative 'event_tree'
|
|
7
|
+
require_relative '../support/pool_hash'
|
|
8
|
+
|
|
9
|
+
module Low
|
|
10
|
+
module Events
|
|
11
|
+
class EventPool
|
|
12
|
+
include Observers
|
|
13
|
+
|
|
14
|
+
BUFFER_SIZE = 100
|
|
15
|
+
|
|
16
|
+
def initialize
|
|
17
|
+
@event_trees = Support::PoolHash.new(BUFFER_SIZE)
|
|
18
|
+
@request_counts = Support::PoolHash.new(BUFFER_SIZE)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def current_event_tree(event:)
|
|
22
|
+
request_id = request_id(event:)
|
|
23
|
+
|
|
24
|
+
return @event_trees[request_id] if @event_trees[request_id]
|
|
25
|
+
|
|
26
|
+
event_tree = @event_trees.add(request_id, EventTree.new(request_id:))
|
|
27
|
+
trigger action: :new_event_tree, event: event_tree
|
|
28
|
+
|
|
29
|
+
event_tree
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def event_trees
|
|
33
|
+
@event_trees
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def request_id(event:)
|
|
39
|
+
fiber_id = Fiber.current.object_id
|
|
40
|
+
increment_request_counts(fiber_id:) if event.is_a?(RequestEvent)
|
|
41
|
+
"#{fiber_id}-#{@request_counts[fiber_id]}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def increment_request_counts(fiber_id:)
|
|
45
|
+
@request_counts[fiber_id] ||= 0
|
|
46
|
+
@request_counts[fiber_id] += 1
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'observers'
|
|
4
|
+
require_relative 'branch_event'
|
|
5
|
+
|
|
6
|
+
module Low
|
|
7
|
+
module Events
|
|
8
|
+
class EventTree
|
|
9
|
+
include Observers
|
|
10
|
+
|
|
11
|
+
attr_reader :request_id, :root_event, :sequence
|
|
12
|
+
attr_accessor :current_event
|
|
13
|
+
|
|
14
|
+
def initialize(request_id: nil)
|
|
15
|
+
@request_id = request_id
|
|
16
|
+
@root_event = nil
|
|
17
|
+
@current_event = nil
|
|
18
|
+
@sequence = []
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def branch(event:)
|
|
22
|
+
@sequence << event
|
|
23
|
+
|
|
24
|
+
if @root_event.nil?
|
|
25
|
+
@root_event = event
|
|
26
|
+
@current_event = event
|
|
27
|
+
else
|
|
28
|
+
@current_event.children << event
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
trigger action: :branch, event: BranchEvent.new(event_tree: self, event:)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Low
|
|
4
|
+
module Support
|
|
5
|
+
class PoolHash < Hash
|
|
6
|
+
def initialize(max_size)
|
|
7
|
+
@max_size = max_size
|
|
8
|
+
|
|
9
|
+
super()
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def add(key, value)
|
|
13
|
+
# Prune the hash when a new item added.
|
|
14
|
+
if size >= @max_size && !key?(key)
|
|
15
|
+
# TODO: Notify event pool that item was removed.
|
|
16
|
+
_old_key, _old_value = shift
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
self[key] = value
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/version.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lowevent
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.8.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- maedi
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: lowtype
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.4'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.4'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: observers
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: protocol-http
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: providers
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
description: Events and observers for event-driven applications
|
|
69
|
+
email:
|
|
70
|
+
- maediprichard@gmail.com
|
|
71
|
+
executables: []
|
|
72
|
+
extensions: []
|
|
73
|
+
extra_rdoc_files: []
|
|
74
|
+
files:
|
|
75
|
+
- lib/events/hidden_event.rb
|
|
76
|
+
- lib/events/render_event.rb
|
|
77
|
+
- lib/events/request_event.rb
|
|
78
|
+
- lib/events/response_event.rb
|
|
79
|
+
- lib/events/status_event.rb
|
|
80
|
+
- lib/factories/response_factory.rb
|
|
81
|
+
- lib/interfaces/definable.rb
|
|
82
|
+
- lib/interfaces/event.rb
|
|
83
|
+
- lib/lowevent.rb
|
|
84
|
+
- lib/pool/branch_event.rb
|
|
85
|
+
- lib/pool/event_pool.rb
|
|
86
|
+
- lib/pool/event_tree.rb
|
|
87
|
+
- lib/support/pool_hash.rb
|
|
88
|
+
- lib/support/value_object.rb
|
|
89
|
+
- lib/version.rb
|
|
90
|
+
homepage: https://github.com/low-rb/lowevent
|
|
91
|
+
licenses: []
|
|
92
|
+
metadata:
|
|
93
|
+
homepage_uri: https://github.com/low-rb/lowevent
|
|
94
|
+
source_code_uri: https://github.com/low-rb/lowevent/src/branch/main
|
|
95
|
+
rdoc_options: []
|
|
96
|
+
require_paths:
|
|
97
|
+
- lib
|
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: 3.3.0
|
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
|
+
requirements:
|
|
105
|
+
- - ">="
|
|
106
|
+
- !ruby/object:Gem::Version
|
|
107
|
+
version: '0'
|
|
108
|
+
requirements: []
|
|
109
|
+
rubygems_version: 4.0.6
|
|
110
|
+
specification_version: 4
|
|
111
|
+
summary: Observable events
|
|
112
|
+
test_files: []
|