action_pubsub 0.1.1 → 0.2.1

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
  SHA1:
3
- metadata.gz: 84b10ab5fca7e4529071e72418eaf0848f2b76c5
4
- data.tar.gz: 97a02cce5b9147716c7a80a497c2262227bc99c5
3
+ metadata.gz: add736363fea3bee32c27d452e27658e6c15ecca
4
+ data.tar.gz: 343e314ddd56701f6d8b50c68c45a648507f54cf
5
5
  SHA512:
6
- metadata.gz: 2098f79665ee6c3d0b067ab86a2f586613610a60c09e05b8b1b5c5dea6d289d16bbef56b2a1b887c1c408c0031a540fcc9b0e9c208106489776192827e130110
7
- data.tar.gz: 17bd202a32d8393e5d62c34c5e5cf0a93b1760ddb0164721a1477edfb48ff35abb11e96e36c52dc789ffa7cc0e23a3066f88e5975ffff654395fd3f747e50f5d
6
+ metadata.gz: 1d66f335d116c6fe845f82eab144b09499142fd60a7e9ef1bdec5aad16dd76a2f651556a8cdc478d9bec6d7c5dbe593018c0956f9070f914031e7a5c99c9006b
7
+ data.tar.gz: ffc57559d5a8513fc6d372ed00ade3bc9ddd2250c30cf53ccb19eaa637e12fd324b8c2c8e51bc52fd2ec67bb99bed1a5d1a13b59a5af1da0978295f13f57474d
data/Gemfile CHANGED
@@ -2,4 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # gem "concurrent-ruby", :path => "~/gems/ruby-concurrency"
4
4
  # Specify your gem's dependencies in action_pubsub.gemspec
5
+ gem "concurrent-ruby", :github => "ruby-concurrency/concurrent-ruby", :branch => "zero-nine-two"
5
6
  gemspec
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  In process, concurrent observers, loosely modeled after rabbitmq
4
4
 
5
- ## Example
5
+ ## Active Record Example
6
6
 
7
7
  Lets say we have a blog app, and our posts have comments enabled on a case by case basis.
8
8
  When someone leaves a new comment, we want to blast out an email to everyone who
@@ -41,6 +41,101 @@ module Blogger
41
41
  end
42
42
  ```
43
43
 
44
+ ## Non Active Record Subscribers
45
+
46
+ As of 0.2.0, we can make anything subscribable, and publish to specific non "exchange" queues.
47
+
48
+ ``` ruby
49
+ module Blogger
50
+ class Comment < ::ActiveRecord::Base
51
+ after_create :publish_after_create, :publish_after_save
52
+
53
+ def publish_after_create
54
+ ::ActionPubsub.publish('blogger/comment/created')
55
+ end
56
+
57
+ def publish_after_save
58
+ ::ActionPubsub.publish('blogger/comment/saved')
59
+ end
60
+ end
61
+ end
62
+ ```
63
+
64
+ ``` ruby
65
+ class CommentSentimentAnalyzer
66
+ include ::ActionPubsub::HasSubscriptions
67
+ include ::ActionPubsub::ActiveRecord::WithConnection
68
+
69
+ class_attribute :sentiment_scores
70
+ self.sentiment_scores = []
71
+
72
+ on 'blogger/comment/created' do |record|
73
+ result = perform_sentiment_analysis(record)
74
+
75
+ if(result.is_beligerent?)
76
+ record.status = :hidden
77
+ record.sentiment_score = result.value
78
+ else
79
+ record.sentiment_score = result.value
80
+ end
81
+
82
+ self.class.sentiment_scores << record.sentiment_score
83
+
84
+ record.save
85
+ end
86
+
87
+ def perform_sentiment_analysis(record)
88
+ ##hit some 3rd party sentiment analysis api
89
+ return record
90
+ end
91
+
92
+ def average_sentiment
93
+ sentiment_scores.calculate_average
94
+ end
95
+ end
96
+ ```
97
+
98
+ Notes:
99
+ 1. The cool thing about the above, is not only is it a really lean, loosely coupled subscription, but its subscribes *asynchronously*, so we can call the 3rd party sentiment analysis api
100
+ directly from our subscriber without worrying about blocking the main thread.
101
+
102
+ 2. the use of
103
+ ``` ruby
104
+ include ::ActionPubsub::ActiveRecord::WithConnection
105
+ ```
106
+
107
+ This ensures that the active record connection gets checked out and checked back into the pool, else youll run out of connections quickly. If you are not doing anything with active record, dont include it. If you are doing ANYTHING with active record (running a query or anything), make sure to include it, or wrap every on action in a connection checkout block, i.e.
108
+
109
+ ``` ruby
110
+ ::ActiveRecord::Base.connection_pool.with_connection
111
+ ```
112
+
113
+ ### Alternative Methods of Publish/Subscription
114
+
115
+ ``` ruby
116
+ ::ActionPubsub.publish('blogger/comment/created', {:my => :comment})
117
+
118
+ #accessing and publishing to the channel directly
119
+ ::ActionPubsub['blogger/comment/created'] << {:my => :comment}
120
+
121
+ #subscribing to channel directly
122
+ ::ActionPubsub.on('blogger/comment/created') do |comment|
123
+ puts comment.inspect
124
+ end
125
+
126
+ #multiple subscriptions per channel are allowed as well
127
+ ::ActionPubsub.on('blogger/comment/created') do |comment|
128
+ puts "do something else with comment #{comment}"
129
+ end
130
+
131
+ #as well as unique keyed subscriptions by name, i.e.
132
+ ::ActionPubsub.on('blogger/comment/created', :as => '/user/1/blogger/comment/created') do |comment|
133
+ puts "do something specific to user 1 with comment"
134
+ end
135
+
136
+ #will ensure that the existing subscription does not get duplicated.
137
+ ```
138
+
44
139
  ### What is the advantage of this pattern?
45
140
 
46
141
  The advantage is it makes your app incredibly reactive. Rather than have to fatten
@@ -52,12 +147,10 @@ application, and do nothing but react to the events occurring within the system.
52
147
 
53
148
  ### Callbacks
54
149
 
55
- Sure, we could use callbacks, but do we care about any of that if the record has
56
- not been commited to the database? (No we should not). Unless you use
57
- after_commit :on => :create, then your callbacks will attempt to run even if record hasn't been committed,
58
- unless at some point an error or false was returned.
59
-
60
- So as a best practice, we only broadcast the creation after it's been commited.
150
+ The ActiveRecord callbacks from the ActionPubsub::ActiveRecord module, are only fired after_commit.
151
+ If for some reason that's a problem, you probably don't want a subscriber to begin with,
152
+ and should stick with standard callbacks. Meaning, subscribers are primarily intended to perform duties
153
+ relevant to the model, but that do not change the model itself.
61
154
 
62
155
  This also allows for complex chains of events to occur, with no knowledge of each other,
63
156
  but that do their one job, and do it well. If that subscriber happens to create a new record,
@@ -24,8 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_dependency "active_attr"
26
26
  spec.add_dependency "activesupport"
27
- spec.add_dependency "concurrent-ruby"
28
- spec.add_dependency "trax_core"
27
+ spec.add_dependency "concurrent-ruby", "~> 0.9.1"
29
28
  spec.add_development_dependency "bundler", "~> 1.10"
30
29
  spec.add_development_dependency 'guard', '~> 2'
31
30
  spec.add_development_dependency 'guard-rspec', '~> 4'
@@ -5,22 +5,27 @@ require "active_attr"
5
5
  require "concurrent/lazy_register"
6
6
  require "concurrent/actor"
7
7
  require "concurrent/agent"
8
- require "trax_core"
9
8
 
10
9
  module ActionPubsub
11
10
  extend ::ActiveSupport::Autoload
12
11
 
13
12
  autoload :ActiveRecord
13
+ autoload :Actors
14
+ autoload :Balancer
14
15
  autoload :Config
16
+ autoload :Channel
17
+ autoload :Channels
18
+ autoload :Errors
15
19
  autoload :Event
16
- autoload :Exchange
17
- autoload :ExchangeRegistry
20
+ autoload :Exchanges
21
+ autoload :HasSubscriptions
18
22
  autoload :Publish
19
23
  autoload :Publishable
20
24
  autoload :Logging
21
25
  autoload :Subscriber
26
+ autoload :Subscriptions
27
+ autoload :Registry
22
28
  autoload :Queue
23
- autoload :Types
24
29
 
25
30
  @configuration ||= ::ActionPubsub::Config.new
26
31
 
@@ -28,12 +33,29 @@ module ActionPubsub
28
33
  block.call(config)
29
34
  end
30
35
 
36
+ def self.channels
37
+ @channels ||= ::ActionPubsub::Channels.new
38
+ end
39
+
40
+ def self.channel?(channel_path)
41
+ channels.key?(channel_path)
42
+ end
43
+
44
+ def self.disable_all!
45
+ configure do |config|
46
+ config.disabled = true
47
+ end
48
+
49
+ subscriptions.all.map{ |_subscription| _subscription << :terminate! }
50
+ self
51
+ end
52
+
31
53
  def self.event_count
32
54
  @event_count ||= ::Concurrent::Agent.new(0)
33
55
  end
34
56
 
35
- def self.exchange_registry
36
- @exchange_registry ||= ::ActionPubsub::ExchangeRegistry.new
57
+ def self.exchanges
58
+ @exchanges ||= ::ActionPubsub::Exchanges.new
37
59
  end
38
60
 
39
61
  def self.destination_tuple_from_path(path_string)
@@ -50,18 +72,33 @@ module ActionPubsub
50
72
  [segs.join("/"), action]
51
73
  end
52
74
 
75
+ def self.on(*paths, as:nil, &block)
76
+ paths.map do |path|
77
+ target_channel = ::ActionPubsub.channels[path]
78
+ subscription_path = "#{path}:#{as || SecureRandom.uuid}"
79
+
80
+ ::ActionPubsub.subscriptions[subscription_path] ||= ::Concurrent::Actor::Utils::AdHoc.spawn(subscription_path) do
81
+ target_channel << :subscribe
82
+ -> message {
83
+ block.call(message)
84
+ }
85
+ end
86
+ end
87
+ end
88
+
53
89
  def self.symbolize_routing_key(routing_key)
54
90
  :"#{routing_key.split('.').join('_')}"
55
91
  end
56
92
 
93
+ def self.publish(path, message)
94
+ self[path] << message
95
+ end
96
+
57
97
  def self.publish_event(routing_key, event)
58
98
  #need to loop through exchanges and publish to them
59
99
  #maybe there is a better way to do this?
60
- exchange_hash = ::ActionPubsub.exchanges[routing_key].instance_variable_get("@data").value
61
- queue_names = exchange_hash.keys
62
-
63
- queue_names.each do |queue_name|
64
- exchange_registry[routing_key][queue_name] << serialize_event(event)
100
+ exchanges[routing_key].keys.each do |queue_name|
101
+ exchanges[routing_key][queue_name] << serialize_event(event)
65
102
  end
66
103
  end
67
104
 
@@ -69,6 +106,18 @@ module ActionPubsub
69
106
  event
70
107
  end
71
108
 
109
+ def self.subscriptions
110
+ @subscriptions ||= ::ActionPubsub::Subscriptions.new
111
+ end
112
+
113
+ def self.silent_dead_letter_handler
114
+ @silent_dead_letter_handler ||= ::ActionPubsub::Actors::SilentDeadLetterHandler.spawn('action_pubsub/silent_dead_letter_handler')
115
+ end
116
+
117
+ def self.subscription?(path)
118
+ subscriptions.key?(path)
119
+ end
120
+
72
121
  def self.deserialize_event(event)
73
122
  event
74
123
  end
@@ -76,10 +125,10 @@ module ActionPubsub
76
125
  class << self
77
126
  attr_accessor :configuration
78
127
  alias_method :config, :configuration
79
- alias_method :exchanges, :exchange_registry
80
128
 
81
- delegate :register_queue, :to => :exchange_registry
82
- delegate :register_channel, :to => :exchange_registry
83
- delegate :register_exchange, :to => :exchange_registry
129
+ delegate :[], :to => :channels
130
+ delegate :register_queue, :to => :exchanges
131
+ delegate :register_channel, :to => :exchanges
132
+ delegate :register_exchange, :to => :exchanges
84
133
  end
85
134
  end
@@ -7,5 +7,6 @@ module ActionPubsub
7
7
  autoload :Publishable
8
8
  autoload :Subscriber
9
9
  autoload :Subscription
10
+ autoload :WithConnection
10
11
  end
11
12
  end
@@ -30,6 +30,9 @@ module ActionPubsub
30
30
  subklass.event_processed_count = ::Concurrent::AtomicFixnum.new(0)
31
31
  end
32
32
 
33
+ def self.disable_all!
34
+ end
35
+
33
36
  def self.on(event_name, **options, &block)
34
37
  reactions[event_name] = {}.tap do |hash|
35
38
  hash[:block] = block
@@ -69,11 +72,11 @@ module ActionPubsub
69
72
  target_exchange = [exchange_prefix, event_name].join("/")
70
73
  subscriber_key = name.underscore
71
74
  queue_key = [target_exchange, subscriber_key].join("/")
72
-
73
75
  ::ActionPubsub.register_queue(target_exchange, subscriber_key)
74
76
 
75
77
  self.concurrency.times do |i|
76
- self.subscription.spawn("#{queue_key}/#{i}") do
78
+ queue_address = "#{queue_key}/#{i}"
79
+ ::ActionPubsub.subscriptions[queue_address] ||= self.subscription.spawn(queue_address) do
77
80
  self.subscription.bind_subscription(target_exchange, subscriber_key)
78
81
  end
79
82
  end
@@ -4,7 +4,7 @@ module ActionPubsub
4
4
  class_attribute :subscriber
5
5
 
6
6
  def self.bind_subscription(target_exchange, subscriber_key)
7
- ::ActionPubsub.exchange_registry[target_exchange][subscriber_key] << :subscribe
7
+ ::ActionPubsub.exchanges[target_exchange][subscriber_key] << :subscribe
8
8
  -> message {
9
9
  ::ActiveRecord::Base.connection_pool.with_connection do
10
10
  begin
@@ -21,10 +21,10 @@ module ActionPubsub
21
21
  self.class.bind_subscription(target_exchange, subscriber_key)
22
22
  rescue => e
23
23
  #ensure we rebind subscription regardless
24
- self.class.bind_subscription(target_exchange, subscriber_key)
24
+ self.class.bind_subscription(target_exchange, subscriber_key) unless message.is_a?(Symbol)
25
25
  message = ::ActionPubsub.deserialize_event(message)
26
26
 
27
- failure_message = ::ActionPubsub::Types::SubscriptionReactionError.new(
27
+ failure_message = ::ActionPubsub::Errors::SubscriptionReactionErrorMessage.new(
28
28
  :target_exchange => target_exchange,
29
29
  :subscriber_key => subscriber_key,
30
30
  :error => e,
@@ -0,0 +1,19 @@
1
+ module ActionPubsub
2
+ module ActiveRecord
3
+ module WithConnection
4
+ extend ::ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def on(*paths, as:nil, &block)
8
+ wrapped_block = lambda{ |message|
9
+ ::ActiveRecord::Base.connection_pool.with_connection { block.call(message) }
10
+ }
11
+
12
+ _subscriptions = ::ActionPubsub.on(*paths, as:(as || _as), &wrapped_block)
13
+ _subscriptions.each { |_subscription| subscriptions << _subscription }
14
+ subscriptions
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ module ActionPubsub
2
+ module Actors
3
+ extend ::ActiveSupport::Autoload
4
+
5
+ autoload :SilenceDeadLetters
6
+ autoload :SilentDeadLetterHandler
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ #dead letter routing not working ATM
2
+ module ActionPubsub
3
+ module Actors
4
+ class SilentDeadLetterHandler < ::Concurrent::Actor::RestartingContext
5
+ def on_messaage(dead_letter)
6
+ puts "SILENCE DEAD LETTER HANDLER GOT MESSAGE"
7
+ puts dead_letter.inspect
8
+ super(dead_letter)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,37 @@
1
+ module ActionPubsub
2
+ class Balancer < ::Concurrent::Actor::Utils::Balancer
3
+
4
+ def initialize
5
+ @receivers = []
6
+ @buffer = []
7
+ end
8
+
9
+ def on_message(message)
10
+ case message
11
+ when :subscribe
12
+ @receivers << envelope.sender
13
+ distribute
14
+ true
15
+ when :unsubscribe
16
+ @receivers.delete envelope.sender
17
+ true
18
+ when :subscribed?
19
+ @receivers.include? envelope.sender
20
+ else
21
+ @buffer << envelope
22
+ distribute
23
+ ::Concurrent::Actor::Behaviour::MESSAGE_PROCESSED
24
+ end
25
+ end
26
+
27
+ def distribute
28
+ while !@receivers.empty? && !@buffer.empty?
29
+ redirect @receivers.shift, @buffer.shift
30
+ end
31
+ end
32
+
33
+ def dead_letter_routing
34
+ ::ActionPubsub.silent_dead_letter_handler
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,4 @@
1
+ module ActionPubsub
2
+ class Channel < Concurrent::Actor::Utils::Broadcast
3
+ end
4
+ end
@@ -0,0 +1,10 @@
1
+ module ActionPubsub
2
+ class Channels < ::ActionPubsub::Registry
3
+ def [](val)
4
+ return super(val) if key?(val)
5
+
6
+ add(val){ ::ActionPubsub::Channel.spawn(val) }
7
+ super(val)
8
+ end
9
+ end
10
+ end
@@ -6,6 +6,7 @@ module ActionPubsub
6
6
  super(*args)
7
7
 
8
8
  self[:debug] = false
9
+ self[:disabled] = false
9
10
  self[:serializer] = nil
10
11
  self[:_on_error_block] = nil
11
12
  end
@@ -14,6 +15,10 @@ module ActionPubsub
14
15
  ::Concurrent.use_stdlib_logger(Logger::DEBUG) if val
15
16
  end
16
17
 
18
+ def disabled?
19
+ self[:disabled]
20
+ end
21
+
17
22
  def serializer=(val)
18
23
  if val && val.ancestors.include?(::ActiveSupport::Concern)
19
24
  ::ActionPubsub.include(val)
@@ -0,0 +1,16 @@
1
+ require 'active_model'
2
+
3
+ module ActionPubsub
4
+ module Errors
5
+ class SubscriptionReactionErrorMessage
6
+ attr_accessor :message, :error, :target_exchange, :subscriber_key
7
+
8
+ def initialize(*args, message:, error:, target_exchange:nil, subscriber_key:nil, **options)
9
+ @message = message
10
+ @error = error
11
+ @target_exchange = target_exchange
12
+ @subscriber_key = subscriber_key
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ module ActionPubsub
2
+ class Exchanges < ::ActionPubsub::Registry
3
+ def register_queue(exchange_name, subscriber_name)
4
+ queue_name = [exchange_name, subscriber_name].join("/")
5
+ queue_exists = self[exchange_name].all.any?{ |queue| queue.name == queue_name }
6
+ self[exchange_name].add(subscriber_name) { ::ActionPubsub::Queue.spawn(queue_name) } unless queue_exists
7
+ end
8
+
9
+ def register_exchange(exchange_name)
10
+ add(exchange_name) { ::ActionPubsub::Exchanges.new }
11
+ self[exchange_name]
12
+ end
13
+
14
+ def [](val)
15
+ return super(val) if key?(val)
16
+
17
+ add(val){ ::ActionPubsub::Exchanges.new }
18
+ super(val)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module ActionPubsub
2
+ module HasSubscriptions
3
+ extend ::ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :_as
7
+ class_attribute :subscriptions
8
+ self.subscriptions = []
9
+ end
10
+
11
+ module ClassMethods
12
+ def as(val)
13
+ self._as = val
14
+ end
15
+
16
+ def on(*paths, as:nil, &block)
17
+ _subscriptions = ::ActionPubsub.on(*paths, as:(as || _as), &block)
18
+ _subscriptions.each { |_subscription| subscriptions << _subscription }
19
+ subscriptions
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,4 +1,4 @@
1
1
  module ActionPubsub
2
- class Queue < ::Concurrent::Actor::Utils::Balancer
2
+ class Queue < ::ActionPubsub::Balancer
3
3
  end
4
4
  end
@@ -0,0 +1,17 @@
1
+ module ActionPubsub
2
+ class Registry < ::Concurrent::LazyRegister
3
+ def all
4
+ keys.map do |k|
5
+ self[k]
6
+ end
7
+ end
8
+
9
+ def []=(key, val)
10
+ register(key) { val }
11
+ end
12
+
13
+ def keys
14
+ @data.value.keys
15
+ end
16
+ end
17
+ end
@@ -1,39 +1,5 @@
1
- ### NOTE: Don't use this. Only the active record subscriber is working ATM.
2
1
  module ActionPubsub
3
- class Subscriber < ::Concurrent::Actor::Utils::AdHoc
4
- class_attribute :concurrency, :queue, :exchange_prefix, :watches
5
- self.concurrency = 1
6
-
7
- def self.inherited(subklass)
8
- subklass.watches = {}
9
- end
10
-
11
- def self.register_event_watcher(event_name)
12
- target_exchange = [exchange_prefix, event_name].join("/")
13
- subscriber_key = name.underscore
14
- queue_key = [target_exchange, subscriber_key].join("/")
15
-
16
- ::ActionPubsub.register_queue(target_exchange, subscriber_key)
17
-
18
- self.concurrency.times do |i|
19
- spawn("#{queue_key}/#{i}") do
20
- bind_subscription(target_exchange, subscriber_key)
21
- end
22
- end
23
- end
24
-
25
- def self.on(event_name, &block)
26
- watches[event_name] = block
27
- register_event_watcher(event_name)
28
- end
29
-
30
- def self.bind_subscription(target_exchange, subscriber_key)
31
- ::ActionPubsub.exchange_registry[target_exchange][subscriber_key] << :subscribe
32
- -> message {
33
- self.class.watches[message["action"]].call(message["record"])
34
-
35
- self.class.bind_subscription(target_exchange, subscriber_key)
36
- }
37
- end
2
+ class Subscriber
3
+ include ::ActionPubsub::HasSubscriptions
38
4
  end
39
5
  end
@@ -0,0 +1,4 @@
1
+ module ActionPubsub
2
+ class Subscriptions < ::ActionPubsub::Registry
3
+ end
4
+ end
@@ -1,3 +1,3 @@
1
1
  module ActionPubsub
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_pubsub
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Ayre
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-11-03 00:00:00.000000000 Z
11
+ date: 2016-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_attr
@@ -42,30 +42,16 @@ dependencies:
42
42
  name: concurrent-ruby
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: trax_core
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
45
+ - - "~>"
60
46
  - !ruby/object:Gem::Version
61
- version: '0'
47
+ version: 0.9.1
62
48
  type: :runtime
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
- - - ">="
52
+ - - "~>"
67
53
  - !ruby/object:Gem::Version
68
- version: '0'
54
+ version: 0.9.1
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: bundler
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -290,14 +276,23 @@ files:
290
276
  - lib/action_pubsub/active_record/publishable.rb
291
277
  - lib/action_pubsub/active_record/subscriber.rb
292
278
  - lib/action_pubsub/active_record/subscription.rb
279
+ - lib/action_pubsub/active_record/with_connection.rb
280
+ - lib/action_pubsub/actors.rb
281
+ - lib/action_pubsub/actors/silent_dead_letter_handler.rb
282
+ - lib/action_pubsub/balancer.rb
283
+ - lib/action_pubsub/channel.rb
284
+ - lib/action_pubsub/channels.rb
293
285
  - lib/action_pubsub/config.rb
286
+ - lib/action_pubsub/errors.rb
294
287
  - lib/action_pubsub/event.rb
295
- - lib/action_pubsub/exchange_registry.rb
288
+ - lib/action_pubsub/exchanges.rb
289
+ - lib/action_pubsub/has_subscriptions.rb
296
290
  - lib/action_pubsub/queue.rb
291
+ - lib/action_pubsub/registry.rb
297
292
  - lib/action_pubsub/serialization.rb
298
293
  - lib/action_pubsub/serialization/marshal.rb
299
294
  - lib/action_pubsub/subscriber.rb
300
- - lib/action_pubsub/types.rb
295
+ - lib/action_pubsub/subscriptions.rb
301
296
  - lib/action_pubsub/version.rb
302
297
  homepage: http://github.com/jasonayre/action_pubsub
303
298
  licenses:
@@ -1,15 +0,0 @@
1
- module ActionPubsub
2
- class ExchangeRegistry < ::Concurrent::LazyRegister
3
- def register_queue(exchange_name, subscriber_name)
4
- register_exchange(exchange_name) unless key?(exchange_name)
5
- exchange_hash = self[exchange_name].instance_variable_get("@data").value
6
- exchange_keys = exchange_hash.keys
7
- queue_name = [exchange_name, subscriber_name].join("/")
8
- self[exchange_name].add(subscriber_name) { ::ActionPubsub::Queue.spawn(queue_name) }
9
- end
10
-
11
- def register_exchange(exchange_name)
12
- add(exchange_name) { ::Concurrent::LazyRegister.new }
13
- end
14
- end
15
- end
@@ -1,19 +0,0 @@
1
- require 'trax_core'
2
-
3
- module ActionPubsub
4
- class Types < ::Trax::Core::Blueprint
5
- class SubscriptionReactionError < ::Trax::Core::Types::Struct
6
- string :target_exchange
7
- string :subscriber_key
8
-
9
- attr_accessor :message, :error
10
-
11
- def initialize(*args, message:, error:, **options)
12
- super(*args, **options)
13
-
14
- @message = message
15
- @error = error
16
- end
17
- end
18
- end
19
- end