standard-procedure-plumbing 0.1.1 → 0.1.2
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/CHANGELOG.md +5 -0
- data/README.md +0 -2
- data/checksums/standard-procedure-plumbing-0.1.2.gem.sha512 +1 -0
- data/lib/plumbing/blocked_pipe.rb +7 -17
- data/lib/plumbing/error.rb +2 -2
- data/lib/plumbing/event.rb +1 -13
- data/lib/plumbing/filter.rb +7 -9
- data/lib/plumbing/pipe.rb +2 -1
- data/lib/plumbing/version.rb +1 -1
- data/lib/plumbing.rb +0 -1
- metadata +7 -36
- data/Guardfile +0 -32
- data/lib/plumbing/concurrent/pipe.rb +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0bfd8678cd958f92a30d6c1879e664ac790637b400a2fd73302a7ed60a3b450
|
4
|
+
data.tar.gz: f06824216f1d2da14fa645b0f246106180e6e8e69f8fa7d5526e8a343ac77923
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac2e9872aba1ecb6c4f2831ee6da3689afdcf1162c5bc0b65eaa2298ae1a00f4d698fb7909c34e10daa6b14cd10bcd8ab54cd92839fab7a1107cd93de831c2c5
|
7
|
+
data.tar.gz: 64f585e329a112504b692b788d6b6c9562bc188eb9c621a33001f2aed69d92c6260909c8a3df174436bfeda345791b7ca370afb09fdad2d281d466efcb0784fc
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -95,8 +95,6 @@ end
|
|
95
95
|
# => "two"
|
96
96
|
```
|
97
97
|
|
98
|
-
There is also [Plumbing::Concurrent::Pipe](/lib/plumbing/concurrent/pipe.rb) that uses a Ractor to dispatch events. Use with caution as Ractors are still experimental, plus they have strict conditions about the data that can be passed across Ractor boundaries.
|
99
|
-
|
100
98
|
## Plumbing::Chain - a chain of operations that occur in sequence
|
101
99
|
|
102
100
|
Define a sequence of operations that proceed in order, passing their output from one operation as the input to another.
|
@@ -0,0 +1 @@
|
|
1
|
+
18d6d3138d2879c1672ab60b1534a6bc382e99a67adb4f8eff9c60ffb96b78b148bffac54ff1f7e78a2da1fc36d000041806b3a73993416c62279ef3ca09beba
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require "dry/types"
|
2
1
|
require_relative "error"
|
3
2
|
require_relative "event"
|
4
3
|
|
@@ -7,14 +6,6 @@ module Plumbing
|
|
7
6
|
# This class is "blocked", in that it won't push any events to registered observers.
|
8
7
|
# Instead, this is the basis for subclasses like [Plumbing::Pipe] which actually allow events to flow through them.
|
9
8
|
class BlockedPipe
|
10
|
-
module Types
|
11
|
-
include Dry::Types()
|
12
|
-
# Events must be Plumbing::Event instances or subclasses
|
13
|
-
Event = Instance(Plumbing::Event)
|
14
|
-
# Observers must have a `call` method
|
15
|
-
Observer = Interface(:call)
|
16
|
-
end
|
17
|
-
|
18
9
|
# Create a new BlockedPipe
|
19
10
|
# Subclasses should call `super()` to ensure the pipe is initialised corrected
|
20
11
|
def initialize
|
@@ -25,13 +16,13 @@ module Plumbing
|
|
25
16
|
# @param event [Plumbing::Event] the event to push into the pipe
|
26
17
|
# Subclasses should implement this method
|
27
18
|
def << event
|
28
|
-
raise PipeIsBlocked
|
19
|
+
raise Plumbing::PipeIsBlocked
|
29
20
|
end
|
30
21
|
|
31
22
|
# A shortcut to creating and then pushing an event
|
32
23
|
# @param event_type [String] representing the type of event this is
|
33
24
|
# @param data [Hash] representing the event-specific data to be passed to the observers
|
34
|
-
def notify event_type,
|
25
|
+
def notify event_type, data = nil
|
35
26
|
Event.new(type: event_type, data: data).tap do |event|
|
36
27
|
self << event
|
37
28
|
end
|
@@ -42,11 +33,10 @@ module Plumbing
|
|
42
33
|
# @param &block [Block] (optional)
|
43
34
|
# @return an object representing this observer (dependent upon the implementation of the pipe itself)
|
44
35
|
# Either a `callable` or a `block` must be supplied. If the latter, it is converted to a [Proc]
|
45
|
-
def add_observer
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
36
|
+
def add_observer observer = nil, &block
|
37
|
+
observer ||= block.to_proc
|
38
|
+
raise Plumbing::InvalidObserver.new "observer_does_not_respond_to_call" unless observer.respond_to? :call
|
39
|
+
@observers << observer
|
50
40
|
end
|
51
41
|
|
52
42
|
# Remove an observer from this pipe
|
@@ -83,7 +73,7 @@ module Plumbing
|
|
83
73
|
# @return [Plumbing::Event]
|
84
74
|
# Subclasses should implement this method
|
85
75
|
def get_next_event
|
86
|
-
raise PipeIsBlocked
|
76
|
+
raise Plumbing::PipeIsBlocked
|
87
77
|
end
|
88
78
|
|
89
79
|
# Start the event loop
|
data/lib/plumbing/error.rb
CHANGED
@@ -9,10 +9,10 @@ module Plumbing
|
|
9
9
|
class PostConditionError < Error; end
|
10
10
|
|
11
11
|
# Error raised because an invalid [Event] object was pushed into the pipe
|
12
|
-
InvalidEvent
|
12
|
+
class InvalidEvent < Error; end
|
13
13
|
|
14
14
|
# Error raised because an invalid observer was registered
|
15
|
-
InvalidObserver
|
15
|
+
class InvalidObserver < Error; end
|
16
16
|
|
17
17
|
# Error raised because a BlockedPipe was used instead of an actual implementation of a Pipe
|
18
18
|
class PipeIsBlocked < Plumbing::Error; end
|
data/lib/plumbing/event.rb
CHANGED
@@ -1,17 +1,5 @@
|
|
1
|
-
require "dry/types"
|
2
|
-
require "dry/struct"
|
3
|
-
|
4
1
|
module Plumbing
|
5
2
|
# An immutable data structure representing an Event
|
6
|
-
|
7
|
-
module Types
|
8
|
-
include Dry::Types()
|
9
|
-
SequenceNumber = Strict::Integer
|
10
|
-
Type = Strict::String
|
11
|
-
Data = Strict::Hash.map(Coercible::Symbol, Nominal::Any).default({}.freeze)
|
12
|
-
end
|
13
|
-
|
14
|
-
attribute :type, Types::Type
|
15
|
-
attribute :data, Types::Data
|
3
|
+
Event = Data.define :type, :data do
|
16
4
|
end
|
17
5
|
end
|
data/lib/plumbing/filter.rb
CHANGED
@@ -1,14 +1,9 @@
|
|
1
|
-
require "dry/types"
|
2
1
|
require_relative "blocked_pipe"
|
3
2
|
|
4
3
|
module Plumbing
|
5
4
|
# A pipe that filters events from a source pipe
|
6
5
|
class Filter < BlockedPipe
|
7
|
-
|
8
|
-
include Dry::Types()
|
9
|
-
Source = Instance(Plumbing::BlockedPipe)
|
10
|
-
EventTypes = Array.of(Plumbing::Event::Types::Type)
|
11
|
-
end
|
6
|
+
class InvalidFilter < Error; end
|
12
7
|
|
13
8
|
# Chain this pipe to the source pipe
|
14
9
|
# @param source [Plumbing::BlockedPipe]
|
@@ -16,9 +11,11 @@ module Plumbing
|
|
16
11
|
# @param rejects [Array[String]] event types that this filter will not allow through
|
17
12
|
def initialize source:, accepts: [], rejects: []
|
18
13
|
super()
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
raise InvalidFilter.new "source must be a Plumbing::BlockedPipe descendant" unless source.is_a? Plumbing::BlockedPipe
|
15
|
+
raise InvalidFilter.new "accepts and rejects must be arrays" unless accepts.is_a?(Array) && rejects.is_a?(Array)
|
16
|
+
@accepted_event_types = accepts
|
17
|
+
@rejected_event_types = rejects
|
18
|
+
source.add_observer do |event|
|
22
19
|
filter_and_republish(event)
|
23
20
|
end
|
24
21
|
end
|
@@ -26,6 +23,7 @@ module Plumbing
|
|
26
23
|
private
|
27
24
|
|
28
25
|
def filter_and_republish event
|
26
|
+
raise InvalidEvent.new "event is not a Plumbing::Event" unless event.is_a? Plumbing::Event
|
29
27
|
return nil if @accepted_event_types.any? && !@accepted_event_types.include?(event.type)
|
30
28
|
return nil if @rejected_event_types.include? event.type
|
31
29
|
dispatch event
|
data/lib/plumbing/pipe.rb
CHANGED
data/lib/plumbing/version.rb
CHANGED
data/lib/plumbing.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: standard-procedure-plumbing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rahoul Baruah
|
@@ -9,36 +9,8 @@ autorequire:
|
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
11
|
date: 2024-08-14 00:00:00.000000000 Z
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
name: dry-types
|
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
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: dry-struct
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
description: An event pipeline
|
12
|
+
dependencies: []
|
13
|
+
description: A composable event pipeline and sequential pipelines of operations
|
42
14
|
email:
|
43
15
|
- rahoulb@echodek.co
|
44
16
|
executables: []
|
@@ -51,15 +23,14 @@ files:
|
|
51
23
|
- ".standard.yml"
|
52
24
|
- CHANGELOG.md
|
53
25
|
- CODE_OF_CONDUCT.md
|
54
|
-
- Guardfile
|
55
26
|
- LICENSE
|
56
27
|
- README.md
|
57
28
|
- Rakefile
|
58
29
|
- checksums/standard-procedure-plumbing-0.1.1.gem.sha512
|
30
|
+
- checksums/standard-procedure-plumbing-0.1.2.gem.sha512
|
59
31
|
- lib/plumbing.rb
|
60
32
|
- lib/plumbing/blocked_pipe.rb
|
61
33
|
- lib/plumbing/chain.rb
|
62
|
-
- lib/plumbing/concurrent/pipe.rb
|
63
34
|
- lib/plumbing/error.rb
|
64
35
|
- lib/plumbing/event.rb
|
65
36
|
- lib/plumbing/filter.rb
|
@@ -71,8 +42,8 @@ licenses: []
|
|
71
42
|
metadata:
|
72
43
|
allowed_push_host: https://rubygems.org
|
73
44
|
homepage_uri: https://theartandscienceofruby.com
|
74
|
-
source_code_uri: https://github.com
|
75
|
-
changelog_uri: https://github.com
|
45
|
+
source_code_uri: https://github.com/standard-procedure/plumbing
|
46
|
+
changelog_uri: https://github.com/standard-procedure/plumbing/blob/main/CHANGELOG.md
|
76
47
|
post_install_message:
|
77
48
|
rdoc_options: []
|
78
49
|
require_paths:
|
@@ -91,5 +62,5 @@ requirements: []
|
|
91
62
|
rubygems_version: 3.5.9
|
92
63
|
signing_key:
|
93
64
|
specification_version: 4
|
94
|
-
summary:
|
65
|
+
summary: Plumbing - various pipelines for your ruby application
|
95
66
|
test_files: []
|
data/Guardfile
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
ignore(/bin/, /log/, /public/, /storage/, /tmp/)
|
2
|
-
|
3
|
-
group :formatting do
|
4
|
-
guard :standardrb, fix: true, all_on_start: true, progress: true do
|
5
|
-
watch(/.+\.rb$/)
|
6
|
-
watch(/.+\.thor$/)
|
7
|
-
watch(/.+\.rake$/)
|
8
|
-
watch(/Guardfile$/)
|
9
|
-
watch(/Rakefile$/)
|
10
|
-
watch(/Gemfile$/)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
group :development do
|
15
|
-
guard :rspec, cmd: "bundle exec rspec" do
|
16
|
-
watch("spec/.+_helper.rb") { "spec" }
|
17
|
-
watch(%r{^spec/.+_spec\.rb$})
|
18
|
-
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
19
|
-
end
|
20
|
-
|
21
|
-
guard :bundler do
|
22
|
-
require "guard/bundler"
|
23
|
-
require "guard/bundler/verify"
|
24
|
-
helper = Guard::Bundler::Verify.new
|
25
|
-
|
26
|
-
files = ["Gemfile"]
|
27
|
-
files += Dir["*.gemspec"] if files.any? { |f| helper.uses_gemspec?(f) }
|
28
|
-
|
29
|
-
# Assume files are symlinked from somewhere
|
30
|
-
files.each { |file| watch(helper.real_path(file)) }
|
31
|
-
end
|
32
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
require "dry/types"
|
2
|
-
require_relative "../blocked_pipe"
|
3
|
-
|
4
|
-
module Plumbing
|
5
|
-
module Concurrent
|
6
|
-
class Pipe < Plumbing::BlockedPipe
|
7
|
-
module Types
|
8
|
-
include Dry::Types()
|
9
|
-
# Observers must be Ractors
|
10
|
-
Observer = Instance(Ractor)
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
super
|
15
|
-
@queue = Ractor.new(self) do |instance|
|
16
|
-
while (message = Ractor.receive) != :shutdown
|
17
|
-
case message.first
|
18
|
-
when :add_observer then instance.send :add_observing_ractor, message.last
|
19
|
-
when :is_observer? then Ractor.yield(instance.send(:is_observing_ractor?, message.last))
|
20
|
-
when :remove_observer then instance.send :remove_observing_ractor, message.last
|
21
|
-
else instance.send :dispatch, message.last
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def add_observer ractor = nil, &block
|
28
|
-
Plumbing::Concurrent::Pipe::Types::Observer[ractor].tap do |observer|
|
29
|
-
@queue << [:add_observer, observer]
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def remove_observer ractor = nil, &block
|
34
|
-
@queue << [:remove_observer, ractor]
|
35
|
-
end
|
36
|
-
|
37
|
-
def is_observer? ractor
|
38
|
-
@queue << [:is_observer?, ractor]
|
39
|
-
@queue.take
|
40
|
-
end
|
41
|
-
|
42
|
-
def << event
|
43
|
-
@queue << [:dispatch, Plumbing::BlockedPipe::Types::Event[event]]
|
44
|
-
end
|
45
|
-
|
46
|
-
def shutdown
|
47
|
-
@queue << :shutdown
|
48
|
-
super
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def dispatch event
|
54
|
-
@observers.each do |observer|
|
55
|
-
observer << event
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def add_observing_ractor observer
|
60
|
-
@observers << observer
|
61
|
-
end
|
62
|
-
|
63
|
-
def is_observing_ractor? observer
|
64
|
-
@observers.include? observer
|
65
|
-
end
|
66
|
-
|
67
|
-
def remove_observing_ractor observer
|
68
|
-
@observers.delete observer
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|