chasqui 1.0.0.pre.rc1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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