chasqui 1.0.0.pre.rc1 → 1.0.0

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +90 -78
  4. data/chasqui.gemspec +1 -1
  5. data/lib/chasqui.rb +83 -5
  6. data/lib/chasqui/cli.rb +8 -2
  7. data/lib/chasqui/config.rb +70 -8
  8. data/lib/chasqui/{queue_adapters → queue_adapter}/redis_queue_adapter.rb +6 -12
  9. data/lib/chasqui/subscriber.rb +1 -78
  10. data/lib/chasqui/subscription_builder.rb +135 -0
  11. data/lib/chasqui/subscription_builder/resque_subscription_builder.rb +31 -0
  12. data/lib/chasqui/subscription_builder/sidekiq_subscription_builder.rb +27 -0
  13. data/lib/chasqui/subscriptions.rb +20 -38
  14. data/lib/chasqui/version.rb +1 -1
  15. data/spec/integration/pubsub_examples.rb +1 -0
  16. data/spec/integration/setup/resque.rb +38 -1
  17. data/spec/integration/setup/sidekiq.rb +40 -1
  18. data/spec/lib/chasqui/brokers/redis_broker_spec.rb +12 -10
  19. data/spec/lib/chasqui/config_spec.rb +3 -3
  20. data/spec/lib/chasqui/{queue_adapters → queue_adapter}/redis_queue_adapter_spec.rb +6 -19
  21. data/spec/lib/chasqui/subscriber_spec.rb +4 -114
  22. data/spec/lib/chasqui/subscription_builder/resque_subscription_builder_spec.rb +20 -0
  23. data/spec/lib/chasqui/subscription_builder/sidekiq_subscription_builder_spec.rb +27 -0
  24. data/spec/lib/chasqui/subscription_builder_spec.rb +41 -0
  25. data/spec/lib/chasqui/subscriptions_spec.rb +4 -4
  26. data/spec/lib/chasqui_spec.rb +76 -12
  27. data/spec/support/chasqui_spec_helpers.rb +0 -21
  28. data/spec/support/fake_worker.rb +2 -0
  29. data/spec/support/shared_examples/subscription_builder_examples.rb +99 -0
  30. metadata +22 -16
  31. data/lib/chasqui/worker.rb +0 -81
  32. data/spec/integration/setup/subscribers.rb +0 -30
  33. data/spec/lib/chasqui/worker_spec.rb +0 -96
  34. data/spec/support/fake_subscriber.rb +0 -13
@@ -13,8 +13,6 @@ module ChasquiSpecHelpers
13
13
  end
14
14
 
15
15
  def reset_chasqui_workers
16
- Chasqui::Worker.workers.clear
17
-
18
16
  Chasqui::Workers.constants.each do |c|
19
17
  Chasqui::Workers.send :remove_const, c
20
18
  end
@@ -32,23 +30,4 @@ module ChasquiSpecHelpers
32
30
  def flush_redis
33
31
  nnredis.keys('*').each { |k| nnredis.del k }
34
32
  end
35
-
36
- def new_subscriber(class_name, options={})
37
- queue = options.fetch :queue
38
- channel = options.fetch :channel
39
-
40
- @subscriber_registry ||= {}
41
-
42
- if @subscriber_registry[class_name] && options[:force]
43
- Object.send :remove_const, class_name
44
- @subscriber_registry[class_name] = nil
45
- end
46
-
47
- @subscriber_registry[class_name] ||= Class.new
48
-
49
- @subscriber_registry[class_name].tap do |sub|
50
- sub.send :include, Chasqui::Subscriber
51
- sub.subscribe channel: channel, queue: queue
52
- end
53
- end
54
33
  end
@@ -0,0 +1,2 @@
1
+ class FakeWorker
2
+ end
@@ -0,0 +1,99 @@
1
+ shared_examples 'a subscription builder' do |worker|
2
+ before { reset_chasqui_workers }
3
+
4
+ # hook for any backend specific assertions on the generated worker class
5
+ # for a proc
6
+ def expect_worker_to_support_backend(worker)
7
+ # noop
8
+ end
9
+
10
+ describe '#on' do
11
+ let(:channel) { 'busy.channel' }
12
+ let(:queue) { 'pubsub' }
13
+
14
+ let(:subscriptions) { double }
15
+
16
+ let(:builder) { described_class.new subscriptions }
17
+
18
+ it 'subscribes the worker to the channel' do
19
+ expect(subscriptions).to receive(:register) do |subscriber|
20
+ expect(subscriber.channel).to eq(channel)
21
+ expect(subscriber.worker).to eq(worker)
22
+ expect(subscriber.queue).to eq(queue)
23
+ end
24
+
25
+ builder.on channel, worker
26
+ end
27
+
28
+ it 'prefixes the queue name' do
29
+ full_queue_name = "app_id:#{queue}"
30
+
31
+ expect(subscriptions).to receive(:register) do |subscriber|
32
+ expect(subscriber.channel).to eq(channel)
33
+ expect(subscriber.worker).to eq(worker)
34
+ expect(subscriber.queue).to eq(full_queue_name)
35
+ end
36
+
37
+ builder.on channel, worker, queue_prefix: 'app_id'
38
+
39
+ expect(queue_name(worker)).to eq(full_queue_name)
40
+ end
41
+
42
+ it 'uses a different queue' do
43
+ expect(subscriptions).to receive(:register) do |subscriber|
44
+ expect(subscriber.channel).to eq(channel)
45
+ expect(subscriber.worker).to eq(worker)
46
+ expect(subscriber.queue).to eq('other:queue')
47
+ end
48
+
49
+ builder.on channel, worker, queue: 'other:queue'
50
+
51
+ expect(queue_name(worker)).to eq('other:queue')
52
+ end
53
+
54
+ it 'does something expected when both options are used' do
55
+ expect(subscriptions).to receive(:register) do |subscriber|
56
+ expect(subscriber.channel).to eq(channel)
57
+ expect(subscriber.worker).to eq(worker)
58
+ expect(subscriber.queue).to eq('prefix:other:queue')
59
+ end
60
+
61
+ builder.on channel, worker, queue: 'other:queue', queue_prefix: 'prefix'
62
+
63
+ expect(queue_name(worker)).to eq('prefix:other:queue')
64
+ end
65
+
66
+ it 'converts a proc to a worker' do
67
+ expect(subscriptions).to receive(:register) do |subscriber|
68
+ queue = "app_id:#{Chasqui.default_queue}"
69
+
70
+ expect(subscriber.channel).to eq('busy.channel')
71
+ expect(subscriber.queue).to eq(queue)
72
+
73
+ worker = subscriber.worker
74
+ expect(worker.name).to eq('Chasqui::Workers::BusyChannelWorker')
75
+ expect(queue_name(worker)).to eq(queue)
76
+
77
+ event = { 'payload' => [3] }
78
+ expect(perform(worker, event)).to eq(6)
79
+ expect_worker_to_support_backend(worker)
80
+ end
81
+
82
+ builder.on channel, ->(event, x) { x + x }, queue_prefix: 'app_id'
83
+ end
84
+
85
+ context 'default options' do
86
+ let(:builder) do
87
+ described_class.new subscriptions, queue_prefix: 'unique', queue: 'low-priority'
88
+ end
89
+
90
+ it 'uses options supplied during initialization when not supplied to #on' do
91
+ expect(subscriptions).to receive(:register) do |subscriber|
92
+ expect(subscriber.queue).to eq('unique:high-priority')
93
+ end
94
+
95
+ builder.on channel, worker, queue: 'high-priority'
96
+ end
97
+ end
98
+ end
99
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chasqui
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.rc1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Bach
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-12 00:00:00.000000000 Z
11
+ date: 2015-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -164,33 +164,37 @@ files:
164
164
  - lib/chasqui/cli.rb
165
165
  - lib/chasqui/config.rb
166
166
  - lib/chasqui/queue_adapter.rb
167
- - lib/chasqui/queue_adapters/redis_queue_adapter.rb
167
+ - lib/chasqui/queue_adapter/redis_queue_adapter.rb
168
168
  - lib/chasqui/subscriber.rb
169
+ - lib/chasqui/subscription_builder.rb
170
+ - lib/chasqui/subscription_builder/resque_subscription_builder.rb
171
+ - lib/chasqui/subscription_builder/sidekiq_subscription_builder.rb
169
172
  - lib/chasqui/subscriptions.rb
170
173
  - lib/chasqui/version.rb
171
- - lib/chasqui/worker.rb
172
174
  - spec/integration/pubsub_examples.rb
173
175
  - spec/integration/resque_spec.rb
174
176
  - spec/integration/setup/resque.rb
175
177
  - spec/integration/setup/sidekiq.rb
176
- - spec/integration/setup/subscribers.rb
177
178
  - spec/integration/sidekiq_spec.rb
178
179
  - spec/lib/chasqui/broker_spec.rb
179
180
  - spec/lib/chasqui/brokers/redis_broker_spec.rb
180
181
  - spec/lib/chasqui/cli_spec.rb
181
182
  - spec/lib/chasqui/config_spec.rb
182
183
  - spec/lib/chasqui/fake_queue_adapter_spec.rb
183
- - spec/lib/chasqui/queue_adapters/redis_queue_adapter_spec.rb
184
+ - spec/lib/chasqui/queue_adapter/redis_queue_adapter_spec.rb
184
185
  - spec/lib/chasqui/subscriber_spec.rb
186
+ - spec/lib/chasqui/subscription_builder/resque_subscription_builder_spec.rb
187
+ - spec/lib/chasqui/subscription_builder/sidekiq_subscription_builder_spec.rb
188
+ - spec/lib/chasqui/subscription_builder_spec.rb
185
189
  - spec/lib/chasqui/subscriptions_spec.rb
186
- - spec/lib/chasqui/worker_spec.rb
187
190
  - spec/lib/chasqui_spec.rb
188
191
  - spec/spec_helper.rb
189
192
  - spec/support/chasqui_spec_helpers.rb
190
193
  - spec/support/fake_logger.rb
191
194
  - spec/support/fake_queue_adapter.rb
192
- - spec/support/fake_subscriber.rb
195
+ - spec/support/fake_worker.rb
193
196
  - spec/support/shared_examples/queue_adapter_examples.rb
197
+ - spec/support/shared_examples/subscription_builder_examples.rb
194
198
  - spec/support/sidekiq_compatibility_check.rb
195
199
  - tmp/.keep
196
200
  homepage: https://github.com/jbgo/chasqui
@@ -208,37 +212,39 @@ required_ruby_version: !ruby/object:Gem::Requirement
208
212
  version: '0'
209
213
  required_rubygems_version: !ruby/object:Gem::Requirement
210
214
  requirements:
211
- - - ">"
215
+ - - ">="
212
216
  - !ruby/object:Gem::Version
213
- version: 1.3.1
217
+ version: '0'
214
218
  requirements: []
215
219
  rubyforge_project:
216
220
  rubygems_version: 2.4.5.1
217
221
  signing_key:
218
222
  specification_version: 4
219
- summary: Chasqui is a simple, lightweight, persistent implementation of the publish-subscribe
220
- (pub/sub) messaging pattern for service oriented architectures.
223
+ summary: Chasqui adds persistent publish-subscribe (pub-sub) messaging capabilities
224
+ to Sidekiq and Resque workers.
221
225
  test_files:
222
226
  - spec/integration/pubsub_examples.rb
223
227
  - spec/integration/resque_spec.rb
224
228
  - spec/integration/setup/resque.rb
225
229
  - spec/integration/setup/sidekiq.rb
226
- - spec/integration/setup/subscribers.rb
227
230
  - spec/integration/sidekiq_spec.rb
228
231
  - spec/lib/chasqui/broker_spec.rb
229
232
  - spec/lib/chasqui/brokers/redis_broker_spec.rb
230
233
  - spec/lib/chasqui/cli_spec.rb
231
234
  - spec/lib/chasqui/config_spec.rb
232
235
  - spec/lib/chasqui/fake_queue_adapter_spec.rb
233
- - spec/lib/chasqui/queue_adapters/redis_queue_adapter_spec.rb
236
+ - spec/lib/chasqui/queue_adapter/redis_queue_adapter_spec.rb
234
237
  - spec/lib/chasqui/subscriber_spec.rb
238
+ - spec/lib/chasqui/subscription_builder/resque_subscription_builder_spec.rb
239
+ - spec/lib/chasqui/subscription_builder/sidekiq_subscription_builder_spec.rb
240
+ - spec/lib/chasqui/subscription_builder_spec.rb
235
241
  - spec/lib/chasqui/subscriptions_spec.rb
236
- - spec/lib/chasqui/worker_spec.rb
237
242
  - spec/lib/chasqui_spec.rb
238
243
  - spec/spec_helper.rb
239
244
  - spec/support/chasqui_spec_helpers.rb
240
245
  - spec/support/fake_logger.rb
241
246
  - spec/support/fake_queue_adapter.rb
242
- - spec/support/fake_subscriber.rb
247
+ - spec/support/fake_worker.rb
243
248
  - spec/support/shared_examples/queue_adapter_examples.rb
249
+ - spec/support/shared_examples/subscription_builder_examples.rb
244
250
  - spec/support/sidekiq_compatibility_check.rb
@@ -1,81 +0,0 @@
1
- module Chasqui
2
- module Chasqui::Workers
3
- end
4
-
5
- class Worker
6
- class << self
7
-
8
- BACKENDS = {
9
- resque: 'ResqueWorkerFactory',
10
- sidekiq: 'SidekiqWorkerFactory'
11
- }
12
-
13
- def create(subscriber)
14
- workers[subscriber.object_id] ||= create_worker(subscriber)
15
- end
16
-
17
- def workers
18
- @workers ||= {}
19
- end
20
-
21
- private
22
-
23
- def check_for_worker_backend
24
- unless BACKENDS.keys.include? Chasqui.worker_backend
25
- msg = "Chasqui.config.worker_backend must be one of #{BACKENDS.keys}"
26
- raise ConfigurationError.new msg
27
- end
28
- end
29
-
30
- def worker_factory
31
- Chasqui.const_get BACKENDS[Chasqui.worker_backend]
32
- end
33
-
34
- def create_worker(subscriber)
35
- check_for_worker_backend
36
- worker = worker_factory.create subscriber
37
- Chasqui::Workers.const_set subscriber.name, worker
38
- end
39
-
40
- end
41
- end
42
-
43
- class ResqueWorkerFactory
44
- def self.create(subscriber)
45
- Class.new do
46
- @queue = subscriber.queue
47
- @subscriber = subscriber
48
-
49
- class << self
50
- attr_reader :subscriber
51
- end
52
-
53
- def self.perform(event)
54
- instance = @subscriber.new event: event, logger: Resque.logger
55
- instance.perform event['payload']
56
- end
57
- end
58
- end
59
- end
60
-
61
- class SidekiqWorkerFactory
62
- def self.create(subscriber)
63
- Class.new do
64
- include Sidekiq::Worker
65
- sidekiq_options 'queue' => 'foo-queue'
66
-
67
- @subscriber = subscriber
68
-
69
- class << self
70
- attr_reader :subscriber
71
- end
72
-
73
- def perform(event)
74
- instance = self.class.subscriber.new event: event, logger: logger
75
- instance.perform event['payload']
76
- end
77
- end
78
- end
79
- end
80
-
81
- end
@@ -1,30 +0,0 @@
1
- def log_event subscriber, payload
2
- Chasqui.redis.rpush "#{subscriber.class.queue}:event_log", subscriber.event.to_json
3
- end
4
-
5
- class UserSignupSubscriber
6
- include Chasqui::Subscriber
7
- subscribe channel: 'user.signup', queue: 'app1'
8
-
9
- def perform(payload)
10
- log_event self, payload
11
- end
12
- end
13
-
14
- class AccountSubscriber
15
- include Chasqui::Subscriber
16
- subscribe channel: ['account.credit', 'account.debit'], queue: 'app2'
17
-
18
- def perform(payload)
19
- log_event self, payload
20
- end
21
- end
22
-
23
- class UserCancelSubscriber
24
- include Chasqui::Subscriber
25
- subscribe channel: 'user.cancel', queue: 'app2'
26
-
27
- def perform(payload)
28
- log_event self, payload
29
- end
30
- end
@@ -1,96 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class MockSubscriber
4
- include Chasqui::Subscriber
5
- subscribe channel: 'foo-channel', prefix: nil, queue: 'foo-queue'
6
-
7
- def perform(payload)
8
- self.class.info[:event] = event
9
- self.class.info[:payload] = payload
10
- self.class.info[:redis] = redis
11
- self.class.info[:logger] = logger
12
- end
13
-
14
- class << self
15
- def info
16
- @info ||= {}
17
- end
18
- end
19
- end
20
-
21
- describe Chasqui::Worker do
22
- before do
23
- reset_config
24
- Chasqui::Worker.workers.clear
25
- MockSubscriber.instance_variable_set :@info, nil
26
- end
27
-
28
- let(:subscriber) { MockSubscriber }
29
-
30
- context 'no worker backend' do
31
- describe '.create' do
32
- it 'raises' do
33
- Chasqui.config.worker_backend = :does_not_exist
34
-
35
- expect(-> {
36
- Chasqui::Worker.create subscriber
37
- }).to raise_error(Chasqui::ConfigurationError)
38
- end
39
- end
40
- end
41
-
42
- context 'resque' do
43
- before { Chasqui.config.worker_backend = :resque }
44
- after { Chasqui::Workers.send :remove_const, :MockSubscriber }
45
-
46
- describe '.create' do
47
- let(:worker) { Chasqui::Worker.create subscriber }
48
-
49
- it { expect(worker.name).to eq('Chasqui::Workers::MockSubscriber') }
50
- it { expect(worker.instance_variable_get(:@queue)).to eq(subscriber.queue) }
51
- it { expect(worker.instance_variable_get(:@subscriber)).to eq(subscriber) }
52
-
53
- it 'delegates #perform to the subscriber' do
54
- event = {
55
- 'channel' => 'foo-channel',
56
- 'payload' => { 'some' => 'data' }
57
- }
58
-
59
- worker.perform event
60
-
61
- expect(subscriber.info[:event]).to eq(event)
62
- expect(subscriber.info[:payload]).to eq(event['payload'])
63
- end
64
- end
65
- end
66
-
67
- if sidekiq_supported_ruby_version?
68
- context 'sidekiq' do
69
- before { Chasqui.config.worker_backend = :sidekiq }
70
- after { Chasqui::Workers.send :remove_const, :MockSubscriber }
71
-
72
- describe '.create' do
73
- let(:worker) { Chasqui::Worker.create subscriber }
74
-
75
- it { expect(worker.name).to eq('Chasqui::Workers::MockSubscriber') }
76
- it { expect(worker.instance_variable_get(:@subscriber)).to eq(subscriber) }
77
- it { expect(worker.sidekiq_options).to include('queue' => 'foo-queue') }
78
- it { expect(worker.included_modules).to include(Sidekiq::Worker) }
79
-
80
- it 'delegates #perform to the subscriber' do
81
- event = {
82
- 'channel' => 'foo-channel',
83
- 'payload' => { 'some' => 'data' }
84
- }
85
-
86
- sidekiq_worker = worker.new
87
- sidekiq_worker.perform event
88
-
89
- expect(subscriber.info[:event]).to eq(event)
90
- expect(subscriber.info[:payload]).to eq(event['payload'])
91
- expect(subscriber.info[:logger]).to eq(sidekiq_worker.logger)
92
- end
93
- end
94
- end
95
- end
96
- end