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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45b26855ceaf54673b25fe4ca63a5e52ab302f585f7653731f444b312dec233f
4
- data.tar.gz: 936af082c395b80018878f9a53842505473f2d9978c97fafc88aea48102153e4
3
+ metadata.gz: a0bfd8678cd958f92a30d6c1879e664ac790637b400a2fd73302a7ed60a3b450
4
+ data.tar.gz: f06824216f1d2da14fa645b0f246106180e6e8e69f8fa7d5526e8a343ac77923
5
5
  SHA512:
6
- metadata.gz: 1cce27319493e32407381bb3623734a5bcd87bd1fa986c83f6d8790afb05376c144f994adfd5e094dd9377ad11ee6bdef3d2348ec279d9f378706d52da49362c
7
- data.tar.gz: 6594ec35d9753979414b79c524a27d3c033bf96739ec750a0774c1cbb0d7b6dc97ec7e64245026f93f42c8083cce1da91fa772cbcecc61edecba7e931e085c10
6
+ metadata.gz: ac2e9872aba1ecb6c4f2831ee6da3689afdcf1162c5bc0b65eaa2298ae1a00f4d698fb7909c34e10daa6b14cd10bcd8ab54cd92839fab7a1107cd93de831c2c5
7
+ data.tar.gz: 64f585e329a112504b692b788d6b6c9562bc188eb9c621a33001f2aed69d92c6260909c8a3df174436bfeda345791b7ca370afb09fdad2d281d466efcb0784fc
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [0.1.2] - 2024-08-14
2
+
3
+ - Removed dependencies
4
+ - Removed Ractor-based concurrent pipe (as I don't trust it yet)
5
+
1
6
  ## [0.1.1] - 2024-08-14
2
7
 
3
8
  - Tidied up the code
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, **data
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 callable = nil, &block
46
- callable ||= block.to_proc
47
- Types::Observer[callable].tap do |observer|
48
- @observers << observer
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
@@ -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 = Dry::Types::ConstraintError
12
+ class InvalidEvent < Error; end
13
13
 
14
14
  # Error raised because an invalid observer was registered
15
- InvalidObserver = Dry::Types::ConstraintError
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
@@ -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
- class Event < Dry::Struct
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
@@ -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
- module Types
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
- @accepted_event_types = Types::EventTypes[accepts]
20
- @rejected_event_types = Types::EventTypes[rejects]
21
- Types::Source[source].add_observer do |event|
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
@@ -11,7 +11,8 @@ module Plumbing
11
11
  end
12
12
 
13
13
  def << event
14
- @fiber.resume Types::Event[event]
14
+ raise Plumbing::InvalidEvent.new "event is not a Plumbing::Event" unless event.is_a? Plumbing::Event
15
+ @fiber.resume event
15
16
  end
16
17
 
17
18
  def shutdown
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plumbing
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/plumbing.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/types"
4
3
  module Plumbing
5
4
  require_relative "plumbing/version"
6
5
 
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.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
- - !ruby/object:Gem::Dependency
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: An event pipeline
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