sidekiq-promise 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 42bd79021c80180e745f9955f20d79676cec7a0a
4
+ data.tar.gz: c83c3a33895da56df06b0d7e59bec12a60dd431d
5
+ SHA512:
6
+ metadata.gz: 5fae2380872872ed025174c8283d4673dee9454a67a60e7d6716e760cf1344b3e6f5df0d2e62bf64d17975a7e5a6b16c81a0b855d7bd2e534a80616a2b2ad1b5
7
+ data.tar.gz: 110ae879d59744fd1a21ffbf1dbdf034d243901348ab9877b21a4358c759bc2ab3b816e18438d16f290a79f9a802910d6b84ea54736b33ba0cc5ab94d5ba4e57
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ rvm:
2
+ - 2.1.1
3
+ - 2.0.0
4
+ services:
5
+ - redis-server
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sidekiq-promise.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,14 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :bundler do
5
+ watch('Gemfile')
6
+ watch(/^.+\.gemspec/)
7
+ end
8
+
9
+ guard :rspec do
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
12
+ watch('spec/spec_helper.rb') { "spec" }
13
+ end
14
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 James Harton
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # Sidekiq::Promise
2
+
3
+ `Sidekiq::Promise` turns Sidekiq workers into asynchronous promises using
4
+ [MrDarcy](https://github.com/jamesotron/MrDarcy).
5
+
6
+ [![Build Status](https://travis-ci.org/jamesotron/sidekick-promise.svg?branch=master)](https://travis-ci.org/jamesotron/sidekick-promise)
7
+
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'sidekiq-promise'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install sidekiq-promise
22
+
23
+ ## Usage
24
+
25
+ In your worker classes, you can now simply include `Sidekiq::Promise`:
26
+
27
+ ```ruby
28
+ class HardWorker
29
+ include Sidekiq::Promise
30
+
31
+ def perform(name, count)
32
+ puts 'Doing hard work'
33
+ end
34
+ end
35
+ ```
36
+
37
+ In your controller or model you can call: `HardWorker.as_promise`
38
+
39
+ ```ruby
40
+ HardWorker.as_promise('bob', 5)
41
+ ```
42
+
43
+ This will return a promise which will not resolve until the job is successfully
44
+ completed.
45
+
46
+ *WARNING* `Sidekiq::Promise` disables retries, so your job, if it fails will
47
+ reject it's promise and Sidekiq will not retry it.
48
+
49
+ ### Why promises you say?
50
+
51
+ Because promises have [amazing chaining properties](https://github.com/jamesotron/MrDarcy#key-points-to-know-about-promises)
52
+ you can use them to build interesting and complicated workflows, eg:
53
+
54
+ ```ruby
55
+ class ProcessWorker
56
+ include Sidekiq::Promise
57
+
58
+ def perform file_to_process
59
+ UnzipWorker.as_promise(file_to_process).then do |dir|
60
+ MrDarcy.all_promises do
61
+ dir.entries.map do |file|
62
+ ImageThumbnailWorker.as_promise(file)
63
+ end
64
+ end
65
+ end.then do
66
+ UserNotificationMailer.all_images_processed
67
+ end
68
+ end
69
+ end
70
+ ```
71
+
72
+ In the above case, we use a worker to unzip a file full of images, then when
73
+ unzipped it simultaneously resizes all the images to thumbnail size, then
74
+ notifies the user that the processing is complete.
75
+
76
+ ## Contributing
77
+
78
+ 1. Fork it ( https://github.com/[my-github-username]/sidekiq-promise/fork )
79
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
80
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
81
+ 4. Push to the branch (`git push origin my-new-feature`)
82
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new :spec
5
+
6
+ task default: :spec
@@ -0,0 +1,12 @@
1
+ module Sidekiq
2
+ module Promise
3
+ class ClientMiddleware < Middleware
4
+
5
+ def call worker_class, job, queue, redis_pool
6
+ job_enqueued job, redis_pool
7
+ yield
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ module Sidekiq
2
+ module Promise
3
+ class Middleware
4
+
5
+ CHANNEL = '/sidekiq_jobs'
6
+
7
+ def job_enqueued job, redis_pool=Sidekiq.redis_pool
8
+ publish_message redis_pool, status: 'enqueued', job: job, jid: job['jid']
9
+ end
10
+
11
+ def job_dequeued job, redis_pool=Sidekiq.redis_pool
12
+ publish_message redis_pool, status: 'dequeued', job: job, jid: job['jid']
13
+ end
14
+
15
+ def job_completed job, redis_pool=Sidekiq.redis_pool
16
+ publish_message redis_pool, status: 'complete', job: job, jid: job['jid']
17
+ end
18
+
19
+ def job_errored job, e, redis_pool=Sidekiq.redis_pool
20
+ publish_message redis_pool, status: 'error', job: job, exception: {class: e.class.to_s, message: e.message, backtrace: e.backtrace}, jid: job['jid']
21
+ end
22
+
23
+ def publish_message redis_pool, message
24
+ redis_pool.with do |redis|
25
+ redis.publish CHANNEL, message.to_json
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,16 @@
1
+ module Sidekiq
2
+ module Promise
3
+ class ServerMiddleware < Middleware
4
+
5
+ def call worker, job, queue
6
+ job_dequeued job
7
+ yield
8
+ job_completed job
9
+ rescue Exception => e
10
+ job_errored job, e
11
+ raise e
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ module Sidekiq
2
+ module Promise
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,74 @@
1
+ module Sidekiq
2
+ module Promise
3
+ class Worker < ::MrDarcy::Promise::Celluloid
4
+
5
+ attr_accessor :jid
6
+
7
+ def initialize worker_klass, *args
8
+ @worker_klass = worker_klass
9
+ @args = args
10
+
11
+ this = self
12
+ block = proc do
13
+ this.send :subscribe
14
+ end
15
+ super block
16
+ end
17
+
18
+ private
19
+
20
+ def evaluate_promise &block
21
+ begin
22
+ block.call ::MrDarcy::Promise::DSL.new(self)
23
+ rescue Exception => e
24
+ reject e
25
+ end
26
+ end
27
+
28
+ def subscribe
29
+ @redis = Sidekiq.redis_pool.checkout
30
+ @redis.subscribe ::Sidekiq::Promise::Middleware::CHANNEL do |on|
31
+ on.subscribe { queue_job }
32
+ on.message do |channel,message|
33
+ message = JSON.parse(message)
34
+ process_message message if applicable? message
35
+ end
36
+ end
37
+ end
38
+
39
+ def unsubscribe
40
+ @redis.unsubscribe
41
+ Sidekiq.redis_pool.checkin
42
+ end
43
+
44
+ def queue_job
45
+ future = ::Celluloid::Future.new do
46
+ @worker_klass.perform_async *@args
47
+ end
48
+ @jid = future.value
49
+ end
50
+
51
+ def applicable? message
52
+ message['jid'] == jid
53
+ end
54
+
55
+ def process_message message
56
+ send "process_#{message['status']}_message", message
57
+ end
58
+
59
+ def process_complete_message message
60
+ unsubscribe
61
+ resolve message['job']
62
+ end
63
+
64
+ def process_error_message message
65
+ unsubscribe
66
+ reject message['exception']
67
+ end
68
+
69
+ def noop *args; end
70
+ alias process_dequeued_message noop
71
+ alias process_enqueued_message noop
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,46 @@
1
+ require "sidekiq/promise/version"
2
+ require 'sidekiq'
3
+ require 'json'
4
+ require 'mr_darcy'
5
+ require 'sidekiq/promise/middleware'
6
+ require 'sidekiq/promise/client_middleware'
7
+ require 'sidekiq/promise/server_middleware'
8
+ require 'sidekiq/promise/worker'
9
+
10
+
11
+ module Sidekiq
12
+ module Promise
13
+ def self.included(base)
14
+ base.send :include, Sidekiq::Worker unless base.ancestors.member? Sidekiq::Worker
15
+ base.extend(ClassMethods)
16
+ base.send :sidekiq_options, retry: false
17
+ unless MrDarcy.driver == :celluloid
18
+ STDOUT.puts "Switched your MrDarcy driver to Celluloid - it was #{MrDarcy.driver}"
19
+ MrDarcy.driver = :celluloid
20
+ end
21
+ end
22
+
23
+ module ClassMethods
24
+ def as_promise(*args)
25
+ ::Sidekiq::Promise::Worker.new self, *args
26
+ end
27
+ end
28
+
29
+ module_function
30
+ def enable_middleware!
31
+ raise RuntimeError, "WARNING: Unable to configure required middleware. sidekiq-promise won't work :(" unless Sidekiq.respond_to? :configure_server
32
+ Sidekiq.configure_server do |config|
33
+ config.server_middleware do |chain|
34
+ chain.add Sidekiq::Promise::ServerMiddleware
35
+ end
36
+ end
37
+ Sidekiq.configure_client do |config|
38
+ config.client_middleware do |chain|
39
+ chain.add Sidekiq::Promise::ClientMiddleware
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ Sidekiq::Promise.enable_middleware!
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sidekiq/promise/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sidekiq-promise"
8
+ spec.version = Sidekiq::Promise::VERSION
9
+ spec.authors = ["James Harton"]
10
+ spec.email = ["james@resistor.io"]
11
+ spec.summary = %q{Wrap Sidekiq jobs in promises}
12
+ spec.description = %q{Treat Sidekiq jobs as asynchronous promises.}
13
+ spec.homepage = "https://github.com/jamesotron/sidekiq-promise"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ %w| rake rspec guard guard-rspec guard-bundler terminal-notifier-guard
23
+ pry |.each do |gem|
24
+ spec.add_development_dependency gem
25
+ end
26
+
27
+ spec.add_dependency 'sidekiq', '~> 3.0.1'
28
+ spec.add_dependency 'mr_darcy', '>= 0.3.0'
29
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Completing job as promise' do
4
+ before(:all) { start_worker }
5
+ after(:all) { kill_worker }
6
+ after { clear_jobs }
7
+
8
+ let(:promise) { SleepyWorker.as_promise(0.1) }
9
+ subject { promise }
10
+
11
+ its(:final) { should be_resolved }
12
+ its(:final) { should_not be_rejected }
13
+
14
+ describe '#then' do
15
+ it 'yields' do
16
+ expect { |b| promise.final.then(&b) }.to yield_control
17
+ end
18
+ end
19
+
20
+ describe '#fail' do
21
+ it 'does not yield' do
22
+ expect { |b| promise.final.fail(&b) }.not_to yield_control
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Crashing job as promise' do
4
+
5
+ before { start_worker }
6
+ after { kill_worker; clear_jobs }
7
+
8
+ let(:promise) { CrashyWorker.as_promise }
9
+ subject { promise }
10
+
11
+ its(:final) { should_not be_resolved }
12
+ its(:final) { should be_rejected }
13
+
14
+ describe '#then' do
15
+ it 'does not yield' do
16
+ expect { |b| promise.final.then(&b) }.not_to yield_control
17
+ end
18
+ end
19
+
20
+ describe '#fail' do
21
+ it 'yields' do
22
+ expect { |b| promise.final.fail(&b) }.to yield_control
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Failing job as promise' do
4
+ before(:all) { start_worker }
5
+ after(:all) { kill_worker }
6
+ before { clear_jobs }
7
+ after { clear_jobs }
8
+
9
+ let(:promise) { RaiseyWorker.as_promise }
10
+ subject { promise }
11
+
12
+ its(:final) { should_not be_resolved }
13
+ its(:final) { should be_rejected }
14
+
15
+ describe '#then' do
16
+ it 'does not yield' do
17
+ expect { |b| promise.final.then(&b) }.not_to yield_control
18
+ end
19
+ end
20
+
21
+ describe '#fail' do
22
+ it 'yields' do
23
+ expect { |b| promise.final.fail(&b) }.to yield_control
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Promising job as promise' do
4
+ before(:all) { start_worker }
5
+ after(:all) { kill_worker }
6
+ before { clear_jobs }
7
+ after { clear_jobs }
8
+
9
+ let(:promise) { PromisingWorker.as_promise }
10
+ subject { promise }
11
+
12
+ its(:final) { should be_resolved }
13
+ its(:final) { should_not be_rejected }
14
+
15
+ describe '#then' do
16
+ it 'yields' do
17
+ expect { |b| promise.final.then(&b) }.to yield_control
18
+ end
19
+ end
20
+
21
+ describe '#fail' do
22
+ it 'does not yield' do
23
+ expect { |b| promise.final.fail(&b) }.not_to yield_control
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sidekiq::Promise::ClientMiddleware do
4
+ let(:worker_class) { Class.new }
5
+ let(:job) { double :job }
6
+ let(:queue) { 'default' }
7
+ let(:redis_pool) { double :redis_pool }
8
+ let(:middleware) { described_class.new }
9
+
10
+ describe '#call' do
11
+ it 'sends a message about enqueuing the job, then yields' do
12
+ expect(middleware).to receive(:job_enqueued).with(job, redis_pool)
13
+ expect { |b| middleware.call(worker_class, job, queue, redis_pool, &b) }.to yield_control
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sidekiq::Promise::Middleware do
4
+ let(:redis_client) { double :redis_client }
5
+ let(:redis_pool) { MockClientPool.new redis_client }
6
+ let(:middleware) { described_class.new }
7
+
8
+ describe '#job_enqueued' do
9
+ it 'delegates to #publish_message' do
10
+ expect(middleware).to receive(:publish_message).with(redis_pool, {status: 'enqueued', job: {}, jid: nil})
11
+ middleware.job_enqueued Hash.new, redis_pool
12
+ end
13
+ end
14
+
15
+ describe '#job_dequeued' do
16
+ it 'delegates to #publish_message' do
17
+ expect(middleware).to receive(:publish_message).with(redis_pool, {status: 'dequeued', job: {}, jid: nil})
18
+ middleware.job_dequeued Hash.new, redis_pool
19
+ end
20
+ end
21
+
22
+ describe '#job_completed' do
23
+ it 'delegates to #publish_message' do
24
+ expect(middleware).to receive(:publish_message).with(redis_pool, {status: 'complete', job: {}, jid: nil})
25
+ middleware.job_completed Hash.new, redis_pool
26
+ end
27
+ end
28
+
29
+ describe '#job_errored' do
30
+ it 'delegates to #publish_message' do
31
+ expect(middleware).to receive(:publish_message).with(redis_pool, {status: 'error', job: {}, jid: nil, exception: {class: 'RuntimeError', message: 'fake error', backtrace: nil}})
32
+ middleware.job_errored Hash.new, RuntimeError.new('fake error'), redis_pool
33
+ end
34
+ end
35
+
36
+ describe '#publish_message' do
37
+ it 'sends the message to redis' do
38
+ message = {message: 'fake message'}
39
+ expect(redis_client).to receive(:publish).with('/sidekiq_jobs', message.to_json)
40
+ middleware.publish_message redis_pool, message
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sidekiq::Promise::ServerMiddleware do
4
+ let(:worker) { double :worker }
5
+ let(:job) { double :job }
6
+ let(:queue) { 'default' }
7
+ let(:middleware) { described_class.new }
8
+
9
+ describe '#call' do
10
+ When 'the job is successful' do
11
+ it 'dequeues the job, then yields, then completes' do
12
+ expect(middleware).to receive(:job_dequeued).with(job)
13
+ expect(middleware).to receive(:job_completed).with(job)
14
+ expect { |b| middleware.call(worker, job, queue, &b) }.to yield_control
15
+ end
16
+ end
17
+
18
+ When 'the jobs fails' do
19
+ it 'dequeues the job, then yeilds, then errors' do
20
+ exception = RuntimeError.new('test exception')
21
+ expect(middleware).to receive(:job_dequeued).with(job)
22
+ expect(middleware).to receive(:job_errored).with(job, exception)
23
+ expect do
24
+ middleware.call(worker,job,queue) { raise exception }
25
+ end.to raise_error
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sidekiq::Promise do
4
+ # not sure how to test this file, so I'm just going to add acceptance specs instead.
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'sidekiq/promise'
2
+ require 'mr_darcy'
3
+ require 'pry'
4
+
5
+ Dir[File.expand_path('../support/**/*.rb', __FILE__)].each { |f| require f }
6
+ Dir[File.expand_path('../workers/**/*.rb', __FILE__)].each { |f| require f }
7
+
8
+ RSpec.configure do |config|
9
+ config.color_enabled = true
10
+ config.formatter = :documentation
11
+ config.extend ContextHelpers
12
+ config.include SidekiqHelpers, example_group: {
13
+ file_path: %r(spec/acceptance)
14
+ }
15
+ end
@@ -0,0 +1,2 @@
1
+ require 'sidekiq/promise'
2
+ Dir[File.expand_path('../workers/**/*.rb', __FILE__)].each { |f| require f }
@@ -0,0 +1,19 @@
1
+ module ContextHelpers
2
+ def When(msg=nil,&block)
3
+ context("When#{left_pad msg}", &block)
4
+ end
5
+
6
+ def Otherwise(msg=nil,&block)
7
+ context("Otherwise#{left_pad msg}", &block)
8
+ end
9
+
10
+ def And(msg=nil,&block)
11
+ context("And#{left_pad msg}", &block)
12
+ end
13
+
14
+ private
15
+
16
+ def left_pad(msg)
17
+ msg ? " #{msg}" : ""
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ class MockClientPool
2
+ attr_accessor :mock_client
3
+
4
+ def initialize mock_client
5
+ self.mock_client = mock_client
6
+ end
7
+
8
+ def with
9
+ yield mock_client
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ require 'sidekiq/api'
2
+
3
+ module SidekiqHelpers
4
+ def start_worker
5
+ return if @worker_pid
6
+ server_path = File.expand_path('../../spec_server.rb', __FILE__)
7
+ @worker_pid = Process.spawn("bundle exec sidekiq -t 0 -r #{server_path}")
8
+ end
9
+
10
+ def kill_worker
11
+ return unless @worker_pid
12
+ Process.kill('TERM', @worker_pid)
13
+ Process.wait(@worker_pid)
14
+ rescue Errno::ESRCH
15
+ ensure
16
+ @worker_pid = nil
17
+ end
18
+
19
+ def clear_jobs
20
+ Sidekiq::Queue.new.clear
21
+ Sidekiq::RetrySet.new.clear
22
+ Sidekiq::ScheduledSet.new.clear
23
+ end
24
+
25
+ end
@@ -0,0 +1,9 @@
1
+ class CrashyWorker
2
+ include Sidekiq::Worker
3
+ include Sidekiq::Promise
4
+
5
+ def perform
6
+ Process.kill('TERM', Process.pid)
7
+ sleep 12
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ class PromisingWorker
2
+ include Sidekiq::Promise
3
+
4
+ def perform
5
+ MrDarcy.all_promises do
6
+ 10.times.map do
7
+ SleepyWorker.as_promise 1
8
+ end
9
+ end.final
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ class RaiseyWorker
2
+ include Sidekiq::Worker
3
+ include Sidekiq::Promise
4
+
5
+ sidekiq_options retry: false, backtrace: false
6
+
7
+ def perform msg="it's time I got a raise"
8
+ raise RuntimeError, msg
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ class SleepyWorker
2
+ include Sidekiq::Worker
3
+ include Sidekiq::Promise
4
+
5
+ def perform delay
6
+ sleep delay
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,232 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sidekiq-promise
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - James Harton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
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: guard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: terminal-notifier-guard
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: sidekiq
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ~>
130
+ - !ruby/object:Gem::Version
131
+ version: 3.0.1
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ~>
137
+ - !ruby/object:Gem::Version
138
+ version: 3.0.1
139
+ - !ruby/object:Gem::Dependency
140
+ name: mr_darcy
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: 0.3.0
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: 0.3.0
153
+ description: Treat Sidekiq jobs as asynchronous promises.
154
+ email:
155
+ - james@resistor.io
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - .gitignore
161
+ - .travis.yml
162
+ - Gemfile
163
+ - Guardfile
164
+ - LICENSE.txt
165
+ - README.md
166
+ - Rakefile
167
+ - lib/sidekiq/promise.rb
168
+ - lib/sidekiq/promise/client_middleware.rb
169
+ - lib/sidekiq/promise/middleware.rb
170
+ - lib/sidekiq/promise/server_middleware.rb
171
+ - lib/sidekiq/promise/version.rb
172
+ - lib/sidekiq/promise/worker.rb
173
+ - sidekiq-promise.gemspec
174
+ - spec/acceptance/completing_job_spec.rb
175
+ - spec/acceptance/crashing_job_spec.rb
176
+ - spec/acceptance/failing_job_spec.rb
177
+ - spec/acceptance/promising_job_spec.rb
178
+ - spec/lib/sidekiq/promise/client_middleware_spec.rb
179
+ - spec/lib/sidekiq/promise/middleware_spec.rb
180
+ - spec/lib/sidekiq/promise/server_middleware_spec.rb
181
+ - spec/lib/sidekiq/promise_spec.rb
182
+ - spec/spec_helper.rb
183
+ - spec/spec_server.rb
184
+ - spec/support/context_helpers.rb
185
+ - spec/support/mock_client_pool.rb
186
+ - spec/support/sidekiq_helpers.rb
187
+ - spec/workers/crashy_worker.rb
188
+ - spec/workers/promising_worker.rb
189
+ - spec/workers/raisey_worker.rb
190
+ - spec/workers/sleepy_worker.rb
191
+ homepage: https://github.com/jamesotron/sidekiq-promise
192
+ licenses:
193
+ - MIT
194
+ metadata: {}
195
+ post_install_message:
196
+ rdoc_options: []
197
+ require_paths:
198
+ - lib
199
+ required_ruby_version: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - '>='
202
+ - !ruby/object:Gem::Version
203
+ version: '0'
204
+ required_rubygems_version: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - '>='
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ requirements: []
210
+ rubyforge_project:
211
+ rubygems_version: 2.2.2
212
+ signing_key:
213
+ specification_version: 4
214
+ summary: Wrap Sidekiq jobs in promises
215
+ test_files:
216
+ - spec/acceptance/completing_job_spec.rb
217
+ - spec/acceptance/crashing_job_spec.rb
218
+ - spec/acceptance/failing_job_spec.rb
219
+ - spec/acceptance/promising_job_spec.rb
220
+ - spec/lib/sidekiq/promise/client_middleware_spec.rb
221
+ - spec/lib/sidekiq/promise/middleware_spec.rb
222
+ - spec/lib/sidekiq/promise/server_middleware_spec.rb
223
+ - spec/lib/sidekiq/promise_spec.rb
224
+ - spec/spec_helper.rb
225
+ - spec/spec_server.rb
226
+ - spec/support/context_helpers.rb
227
+ - spec/support/mock_client_pool.rb
228
+ - spec/support/sidekiq_helpers.rb
229
+ - spec/workers/crashy_worker.rb
230
+ - spec/workers/promising_worker.rb
231
+ - spec/workers/raisey_worker.rb
232
+ - spec/workers/sleepy_worker.rb