kiqit 0.0.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.travis.yml +3 -0
- data/README.md +193 -0
- data/Rakefile +9 -1
- data/init.rb +2 -0
- data/kiqit.gemspec +12 -11
- data/lib/kiqit/args_parser.rb +56 -0
- data/lib/kiqit/config.rb +11 -0
- data/lib/kiqit/job_creator.rb +28 -0
- data/lib/kiqit/payload_helper.rb +20 -0
- data/lib/kiqit/plugins.rb +17 -0
- data/lib/kiqit/railtie.rb +5 -0
- data/lib/kiqit/version.rb +1 -1
- data/lib/kiqit/workers/active_record/lone_worker.rb +19 -0
- data/lib/kiqit/workers/active_record/worker.rb +15 -0
- data/lib/kiqit/workers/base.rb +21 -0
- data/lib/kiqit/workers/objects/lone_worker.rb +16 -0
- data/lib/kiqit/workers/objects/worker.rb +13 -0
- data/lib/kiqit.rb +30 -2
- data/lib/object_perform_later.rb +36 -0
- data/lib/resque_mailer_patch.rb +17 -0
- data/lib/sidekiq/plugins/later/method.rb +88 -0
- data/license +20 -0
- data/spec/lib/kiqit/args_parser_spec.rb +96 -0
- data/spec/lib/kiqit/config_spec.rb +11 -0
- data/spec/lib/kiqit/job_creator_spec.rb +23 -0
- data/spec/lib/kiqit/payload_helper_spec.rb +21 -0
- data/spec/lib/kiqit/plugins_spec.rb +33 -0
- data/spec/lib/kiqit/workers/active_record/worker_spec.rb +5 -0
- data/spec/lib/kiqit/workers/objects/worker_spec.rb +74 -0
- data/spec/lib/object_perform_later_spec.rb +141 -0
- data/spec/lib/perform_later_spec.rb +5 -0
- data/spec/lib/sidekiq/plugins/later/method_spec.rb +121 -0
- data/spec/spec_helper.rb +35 -0
- data/spec/support/database_connection.rb +1 -0
- data/spec/support/database_models.rb +30 -0
- data/spec/support/db/.blank.sqlite3 +0 -0
- data/spec/support/db/test.sqlite3 +0 -0
- metadata +180 -110
- data/.rvmrc +0 -1
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -0,0 +1,193 @@
|
|
1
|
+
[![Build Status](https://secure.travis-ci.org/KensoDev/kiqit.png)](https://secure.travis-ci.org/KensoDev/kiqit)
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
Kiqit is a gem meant to work with the [Sidekiq](http://github.com/mperham/sidekiq) queue system. It was adapted from the Perform Later gem.
|
5
|
+
|
6
|
+
Usually, when working with Sidekiq, you need separate "Worker" classes and you also need to do `Sidekiq.enqueue` whenever you want to add a task to the queue.
|
7
|
+
|
8
|
+
That can be a real hassle if you are adding Sidekiq to an existing project, it can also add quite a bit of code to your system.
|
9
|
+
|
10
|
+
`kiqit` fills this need, it offers a suite to handle all of your queuing needs, both for Objects and for ActiveRecord models.
|
11
|
+
|
12
|
+
## Why?
|
13
|
+
*Why* should you queue something for later?
|
14
|
+
|
15
|
+
You should queue something whenever the method handles some heavy lifting, some timely actions like API, 3rd party HTTP requests and more.
|
16
|
+
|
17
|
+
The basic logic is that whatever you don't need to do NOW, you should do later, this will make your site faster and the users will feel it.
|
18
|
+
|
19
|
+
## Real life use case
|
20
|
+
At [Gogobot](http://gogobot.com) whenever you post a review, there's major score calculation going on. This can sometimes take up to a minute, depending on the user graph.
|
21
|
+
|
22
|
+
The user should not wait for this on submit, it can be queued into later execution.
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
gem install kiqit
|
26
|
+
|
27
|
+
If you are using bundler, simply add
|
28
|
+
`gem "kiqit"` to your Gemfile
|
29
|
+
|
30
|
+
|
31
|
+
## Configuration
|
32
|
+
In an initializer, all you need to say is whether you want perform later to be enabled or not, typically, it will be something like this
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
unless Rails.env.test?
|
36
|
+
Kiqit.config.enabled = true # this will default to false if unset
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
## Usage
|
41
|
+
|
42
|
+
### ActiveRecord
|
43
|
+
|
44
|
+
`kiqit` comes with a special method you can use on ActiveRecord models.
|
45
|
+
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
|
49
|
+
class User < ActiveRecord::Base
|
50
|
+
def long_running_method
|
51
|
+
# Your code here
|
52
|
+
end
|
53
|
+
later :long_running_method
|
54
|
+
|
55
|
+
def long_running_method_2
|
56
|
+
# Your code here
|
57
|
+
end
|
58
|
+
later :long_running_method_2, queue: :some_queue_name
|
59
|
+
|
60
|
+
def lonely_long_running_method
|
61
|
+
# Your code here
|
62
|
+
end
|
63
|
+
later :lonely_long_running_method, :loner => true, queue: :some_queue_name
|
64
|
+
|
65
|
+
def delayed_long_running_method
|
66
|
+
# Your code here
|
67
|
+
end
|
68
|
+
later :delayed_long_running_method, :delay => 30, queue: :some_queue_name
|
69
|
+
end
|
70
|
+
|
71
|
+
```
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
u = User.find(some_user_id)
|
75
|
+
u.long_running_method # Method will be queued into the :generic queue
|
76
|
+
u.long_running_method_2 # Method will be queued into :some_queue_name queue
|
77
|
+
u.lonely_long_running_method # Method will be queued into the :some_queue_name queue, only a single instance of this method can exist in the queue.
|
78
|
+
u.delayed_long_running_method # Method will be queued into :some_queue_name queue only after 30 seconds have passed.
|
79
|
+
```
|
80
|
+
|
81
|
+
You can of course choose to run the method off the queue, just prepend `now_` to the method name and it will be executed in sync.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
u = User.find(some_user_id)
|
85
|
+
u.now_long_running_method
|
86
|
+
```
|
87
|
+
|
88
|
+
### Objects/Classes
|
89
|
+
|
90
|
+
If you want class methods to be queued, you will have to use the `kiqit` special method.
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
class SomeClass
|
94
|
+
def self.some_heavy_lifting_method
|
95
|
+
# Your code here
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.some_more_heavy_lifting(user_id)
|
99
|
+
# Your code here
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
SomeClass.kiqit(:queue_name, :some_heavy_lifting_method)
|
104
|
+
SomeClass.kiqit(:queue_name, :some_more_heavy_lifting, user_id)
|
105
|
+
|
106
|
+
|
107
|
+
```
|
108
|
+
|
109
|
+
If you want the method to be a loner (only a single instance in the queue), you will need to use the `kiqit!` method.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
SomeClass.kiqit!(:queue_name, :some_more_heavy_lifting, user_id)
|
113
|
+
```
|
114
|
+
|
115
|
+
## The params parser
|
116
|
+
`kiqit` has a special class called `ArgsParser`, this class is in charge of *translating* the args you are passing into params that can actually be serialized to JSON cleanly.
|
117
|
+
|
118
|
+
Examples:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
user = User.find(1)
|
122
|
+
Kiqit::ArgsParser.params_to_sidekiq(user) => 'AR:#User:1'
|
123
|
+
|
124
|
+
hotel = Hotel.find(1)
|
125
|
+
Kiqit::ArgsParser.params_to_sidekiq(hotel) => 'AR:#Hotel:1'
|
126
|
+
|
127
|
+
hash = { name: "something", other: "something else" }
|
128
|
+
Kiqit::ArgsParser.params_to_sidekiq(hash)
|
129
|
+
=> ---
|
130
|
+
:name: something
|
131
|
+
:other: something else
|
132
|
+
# Hashes are translated into YAML
|
133
|
+
```
|
134
|
+
|
135
|
+
Basically, the `ArgsParser` class allows you to keep passing any args you want to your methods without worrying about whether they serialize cleanly or not.
|
136
|
+
|
137
|
+
`ArgsParser` also patched `sidekiq-mailer` so you can pass in AR objects to mailers as well.
|
138
|
+
|
139
|
+
## The custom finder
|
140
|
+
I found the need to add a custom finder to the args parser.
|
141
|
+
|
142
|
+
### Why?
|
143
|
+
At Gogobot for example, we use slave databases, those sometimes have lag, so when the finder is executed it returns nil, even though the record is actually on the master.
|
144
|
+
|
145
|
+
So, I added support for custom finders.
|
146
|
+
|
147
|
+
#### Example:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
class CustomFinder
|
151
|
+
def self.find(klass, id)
|
152
|
+
Octopus.using(:master) {
|
153
|
+
klass.where(id: id).first
|
154
|
+
} unless klass.where(id: id).first
|
155
|
+
end
|
156
|
+
end
|
157
|
+
```
|
158
|
+
|
159
|
+
Then in an initializer
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
Kiqit::Plugins.add_finder(CustomFinder)
|
163
|
+
```
|
164
|
+
|
165
|
+
You can also remove the finder in runtime
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
Kiqit::Plugins.clear_finder!
|
169
|
+
```
|
170
|
+
|
171
|
+
So, at Gogobot for example, we will fall back to master if the record was not found on the slave DB.
|
172
|
+
|
173
|
+
|
174
|
+
## Contribute / Bug reports
|
175
|
+
|
176
|
+
If you have an issue with this gem, please open an issue in the main repo, it will help tons if you could supply a failing spec with that, so I can better track where the bug is coming from, if not, no worries, just report I will do my best to address it as fast and efficient as I can.
|
177
|
+
|
178
|
+
If you want to contribute (awesome), open a feature branch, base it on master.
|
179
|
+
|
180
|
+
Be as descriptive as you can in the pull request description, just to be clear what problem you are solving or what feature are you adding.
|
181
|
+
|
182
|
+
## Authors
|
183
|
+
|
184
|
+
Avi Tzurel ([@kensodev](http://twitter.com/kensodev)) http://www.kensodev.com
|
185
|
+
Tom Caspy
|
186
|
+
|
187
|
+
## Contributors
|
188
|
+
|
189
|
+
* Felipe Lima ([@felipecsl](http://twitter.com/felipecsl))
|
190
|
+
http://blog.felipel.com/
|
191
|
+
|
192
|
+
Felipe did awesome work on making sure `kiqit` can work with any args and any number of args passed into the methods.
|
193
|
+
Felipe now has commit rights to the repo.
|
data/Rakefile
CHANGED
data/init.rb
ADDED
data/kiqit.gemspec
CHANGED
@@ -5,11 +5,11 @@ require "kiqit/version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "kiqit"
|
7
7
|
s.version = Kiqit::VERSION
|
8
|
-
s.authors = ["Avi Tzurel"]
|
9
|
-
s.email = ["avi@kensodev.com"]
|
10
|
-
s.homepage = "http://www.
|
11
|
-
s.summary = %q{
|
12
|
-
s.description = %q{
|
8
|
+
s.authors = ["Avi Tzurel", "Tom Caspy"]
|
9
|
+
s.email = ["avi@kensodev.com", "tom@kensodev.com"]
|
10
|
+
s.homepage = "http://www.github.com/kensodev/kiqit"
|
11
|
+
s.summary = %q{Queue any method in any class or instance with no need for additional Worker class and no extra code}
|
12
|
+
s.description = %q{Queue any method in any class or instance with no need for additional Worker class and no extra code}
|
13
13
|
|
14
14
|
s.rubyforge_project = "kiqit"
|
15
15
|
|
@@ -18,11 +18,12 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.
|
21
|
+
s.add_dependency 'sidekiq'
|
22
|
+
s.add_dependency 'activerecord'
|
22
23
|
|
23
|
-
s.add_development_dependency '
|
24
|
-
s.add_development_dependency 'rspec'
|
24
|
+
s.add_development_dependency 'rake'
|
25
25
|
s.add_development_dependency 'rspec-rails'
|
26
|
-
s.add_development_dependency '
|
27
|
-
s.add_development_dependency '
|
28
|
-
|
26
|
+
s.add_development_dependency 'rspec'
|
27
|
+
s.add_development_dependency 'sqlite3'
|
28
|
+
s.add_development_dependency 'fakeredis'
|
29
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Kiqit
|
4
|
+
class ArgsParser
|
5
|
+
# inspired by DelayedJob
|
6
|
+
CLASS_STRING_FORMAT = /^CLASS\:([A-Z][\w\:]+)$/
|
7
|
+
AR_STRING_FORMAT = /^AR\:([A-Z][\w\:]+)\:(\d+)$/
|
8
|
+
YAML_STRING_FORMAT = /\A---/
|
9
|
+
|
10
|
+
def self.args_to_sidekiq(args)
|
11
|
+
return nil unless args
|
12
|
+
return arg_to_sidekiq(args) unless args.is_a?(Array)
|
13
|
+
return args.map { |o| arg_to_sidekiq o }
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.args_from_sidekiq(args)
|
17
|
+
args = args.map { |o|
|
18
|
+
if o
|
19
|
+
o = args_from_sidekiq(o) if o.is_a?(Array)
|
20
|
+
case o
|
21
|
+
when CLASS_STRING_FORMAT
|
22
|
+
$1.constantize
|
23
|
+
when AR_STRING_FORMAT
|
24
|
+
runner_class = $1.constantize
|
25
|
+
id = $2
|
26
|
+
|
27
|
+
if Kiqit::Plugins.finder_class
|
28
|
+
Kiqit::Plugins.finder_class.find(runner_class, id)
|
29
|
+
else
|
30
|
+
runner_class.where(id: id).first
|
31
|
+
end
|
32
|
+
when YAML_STRING_FORMAT
|
33
|
+
YAML.load(o)
|
34
|
+
else
|
35
|
+
o
|
36
|
+
end
|
37
|
+
end
|
38
|
+
} if args
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def self.arg_to_sidekiq(arg)
|
44
|
+
case arg
|
45
|
+
when ActiveRecord::Base
|
46
|
+
"AR:#{arg.class.name}:#{arg.id}"
|
47
|
+
when Class, Module
|
48
|
+
"CLASS:#{arg.name}"
|
49
|
+
when Hash
|
50
|
+
arg.to_yaml
|
51
|
+
else
|
52
|
+
arg
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/kiqit/config.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Kiqit
|
2
|
+
class JobCreator
|
3
|
+
|
4
|
+
attr_reader :queue, :worker, :klass_name, :id, :method
|
5
|
+
attr_accessor :args
|
6
|
+
|
7
|
+
def initialize(queue, worker, klass_name, id, method, *args)
|
8
|
+
@queue = queue
|
9
|
+
@worker = worker
|
10
|
+
@klass_name = klass_name
|
11
|
+
@id = id
|
12
|
+
@method = method
|
13
|
+
@args = args
|
14
|
+
end
|
15
|
+
|
16
|
+
def enqueue(delay=nil)
|
17
|
+
params = {}
|
18
|
+
if delay
|
19
|
+
delay = delay.is_a?(Hash) ? delay[:delay] : delay
|
20
|
+
params["at"] = (Time.now + delay).to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
params.merge!({"queue" => queue, "class" => worker, "args" => [klass_name, id, method, *args]})
|
24
|
+
|
25
|
+
Sidekiq::Client.push(params)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Kiqit
|
2
|
+
class PayloadHelper
|
3
|
+
# Public: Get Digest for the loner key.
|
4
|
+
#
|
5
|
+
# klass - Class name.
|
6
|
+
# method - Method name.
|
7
|
+
# Args - Args to send on the method
|
8
|
+
#
|
9
|
+
# Examples =>
|
10
|
+
# PayloadHelper.get_digest("SomeClass", "some_method", "arg1", "arg2")
|
11
|
+
#
|
12
|
+
def self.get_digest(klass, method, *args)
|
13
|
+
args = args.flatten
|
14
|
+
payload = { :class => klass, :method => method.to_s, :args => args }.to_s
|
15
|
+
digest = Digest::MD5.hexdigest("#{payload}")
|
16
|
+
|
17
|
+
"loner:#{digest}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Kiqit
|
2
|
+
class Plugins
|
3
|
+
def self.finder_class
|
4
|
+
@@finder_class ||= nil
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.add_finder(klass)
|
8
|
+
if klass.respond_to?(:find)
|
9
|
+
@@finder_class = klass
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.clear_finder!
|
14
|
+
@@finder_class = nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/kiqit/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Kiqit
|
2
|
+
module Workers
|
3
|
+
module ActiveRecord
|
4
|
+
class LoneWorker < Kiqit::Workers::Base
|
5
|
+
def perform(klass, id, method, *args)
|
6
|
+
# Remove the loner flag from redis
|
7
|
+
digest = Kiqit::PayloadHelper.get_digest(klass, method, args)
|
8
|
+
Sidekiq.redis.del(digest)
|
9
|
+
|
10
|
+
args = Kiqit::ArgsParser.args_from_sidekiq(args)
|
11
|
+
runner_klass = klass.constantize
|
12
|
+
record = runner_klass.find(id)
|
13
|
+
|
14
|
+
perform_job(record, method, args)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Kiqit
|
2
|
+
module Workers
|
3
|
+
module ActiveRecord
|
4
|
+
class Worker < Kiqit::Workers::Base
|
5
|
+
def perform(klass, id, method, *args)
|
6
|
+
args = Kiqit::ArgsParser.args_from_sidekiq(args)
|
7
|
+
runner_klass = klass.constantize
|
8
|
+
record = runner_klass.find(id)
|
9
|
+
|
10
|
+
perform_job(record, method, args)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Kiqit
|
2
|
+
module Workers
|
3
|
+
class Base
|
4
|
+
|
5
|
+
include Sidekiq::Worker
|
6
|
+
|
7
|
+
protected
|
8
|
+
def perform_job(object, method, arguments)
|
9
|
+
unless arguments.empty?
|
10
|
+
if arguments.size == 1
|
11
|
+
object.send(method, arguments.first)
|
12
|
+
else
|
13
|
+
object.send(method, *arguments)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
object.send(method)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Kiqit
|
2
|
+
module Workers
|
3
|
+
module Objects
|
4
|
+
class LoneWorker < Kiqit::Workers::Base
|
5
|
+
def perform(klass_name, method, *args)
|
6
|
+
digest = Kiqit::PayloadHelper.get_digest(klass_name, method, args)
|
7
|
+
Sidekiq.redis.del(digest)
|
8
|
+
|
9
|
+
arguments = Kiqit::ArgsParser.args_from_sidekiq(args)
|
10
|
+
|
11
|
+
perform_job(klass_name.constantize, method, arguments)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Kiqit
|
2
|
+
module Workers
|
3
|
+
module Objects
|
4
|
+
class Worker < Kiqit::Workers::Base
|
5
|
+
def perform(klass_name, method, *args)
|
6
|
+
arguments = Kiqit::ArgsParser.args_from_sidekiq(args)
|
7
|
+
|
8
|
+
perform_job(klass_name.constantize, method, arguments)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/kiqit.rb
CHANGED
@@ -1,5 +1,33 @@
|
|
1
|
-
require
|
1
|
+
require 'sidekiq'
|
2
|
+
require 'active_support/dependencies'
|
3
|
+
require 'kiqit/version'
|
4
|
+
require 'kiqit/config'
|
5
|
+
require 'kiqit/payload_helper'
|
6
|
+
require 'kiqit/args_parser'
|
7
|
+
require 'kiqit/plugins'
|
8
|
+
require 'kiqit/job_creator'
|
9
|
+
require 'active_record'
|
10
|
+
require 'object_perform_later'
|
11
|
+
require 'kiqit/workers/base'
|
12
|
+
require 'kiqit/workers/active_record/worker'
|
13
|
+
require 'kiqit/workers/active_record/lone_worker'
|
14
|
+
require 'kiqit/workers/objects/worker'
|
15
|
+
require 'kiqit/workers/objects/lone_worker'
|
2
16
|
|
3
17
|
module Kiqit
|
4
|
-
|
18
|
+
def self.config
|
19
|
+
Kiqit::Config
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Sidekiq
|
24
|
+
module Plugins
|
25
|
+
module Later
|
26
|
+
autoload :Method, 'sidekiq/plugins/later/method'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
ActiveSupport.on_load(:active_record) do
|
32
|
+
include Sidekiq::Plugins::Later::Method
|
5
33
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ObjectKiqit
|
2
|
+
def kiqit(queue, method, *args)
|
3
|
+
return perform_now(method, args) unless Kiqit.config.enabled?
|
4
|
+
|
5
|
+
worker = Kiqit::Workers::Objects::Worker
|
6
|
+
kiqit_enqueue(worker, queue, method, args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def kiqit!(queue, method, *args)
|
10
|
+
return perform_now(method, args) unless Kiqit.config.enabled?
|
11
|
+
|
12
|
+
return "EXISTS!" if loner_exists(method, args)
|
13
|
+
|
14
|
+
worker = Kiqit::Workers::Objects::LoneWorker
|
15
|
+
kiqit_enqueue(worker, queue, method, args)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def loner_exists(method, *args)
|
20
|
+
digest = Kiqit::PayloadHelper.get_digest(self.name, method, args)
|
21
|
+
|
22
|
+
!Sidekiq.redis{|i| i.setnx(digest, 'EXISTS')}
|
23
|
+
end
|
24
|
+
|
25
|
+
def kiqit_enqueue(worker, queue, method, args)
|
26
|
+
args = Kiqit::ArgsParser.args_to_sidekiq(args)
|
27
|
+
params = {"queue" => queue, "class" => worker, "args" => [self.name, method, *args]}
|
28
|
+
Sidekiq::Client.push(params)
|
29
|
+
end
|
30
|
+
|
31
|
+
def perform_now(method, args)
|
32
|
+
args.size == 1 ? send(method, args.first) : send(method, *args)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Object.send(:include, ObjectKiqit)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Mailer
|
3
|
+
module ClassMethods
|
4
|
+
def perform(action, *args)
|
5
|
+
args = Kiqit::ArgsParser.args_from_sidekiq(args)
|
6
|
+
self.send(:new, action, *args).message.deliver
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class MessageDecoy
|
11
|
+
def deliver
|
12
|
+
args = Kiqit::ArgsParser.args_to_sidekiq(@args)
|
13
|
+
sidekiq.enqueue(@mailer_class, @method_name, *args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Sidekiq::Plugins::Later::Method
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
def later(method_name, opts={})
|
6
|
+
alias_method "now_#{method_name}", method_name
|
7
|
+
return unless Kiqit.config.enabled?
|
8
|
+
|
9
|
+
define_method "#{method_name}" do |*args|
|
10
|
+
loner = opts.fetch(:loner, false)
|
11
|
+
queue = opts.fetch(:queue, :generic)
|
12
|
+
delay = opts.fetch(:delay, false)
|
13
|
+
klass = Kiqit::Workers::ActiveRecord::Worker
|
14
|
+
klass = Kiqit::Workers::ActiveRecord::LoneWorker if loner
|
15
|
+
args = Kiqit::ArgsParser.args_to_sidekiq(args)
|
16
|
+
digest = Kiqit::PayloadHelper.get_digest(klass, method_name, args)
|
17
|
+
|
18
|
+
if loner
|
19
|
+
return "AR EXISTS!" if Sidekiq.redis{|i| i.get(digest).present?}
|
20
|
+
Sidekiq.redis{|i| i.set(digest, 'EXISTS')}
|
21
|
+
end
|
22
|
+
|
23
|
+
job = Kiqit::JobCreator.new(queue, klass, send(:class).name, send(:id), "now_#{method_name}", *args)
|
24
|
+
job.enqueue(delay)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def kiqit(queue, method, *args)
|
31
|
+
return perform_now(method, args) if plugin_disabled?
|
32
|
+
|
33
|
+
worker = Kiqit::Workers::ActiveRecord::Worker
|
34
|
+
job = Kiqit::JobCreator.new(queue, worker, self.class.name, self.id, method, *args)
|
35
|
+
enqueue_in_sidekiq_or_send(job)
|
36
|
+
end
|
37
|
+
|
38
|
+
def kiqit!(queue, method, *args)
|
39
|
+
return perform_now(method, args) if plugin_disabled?
|
40
|
+
return "AR EXISTS!" if loner_exists(method, args)
|
41
|
+
|
42
|
+
worker = Kiqit::Workers::ActiveRecord::LoneWorker
|
43
|
+
job = Kiqit::JobCreator.new(queue, worker, self.class.name, self.id, method, *args)
|
44
|
+
enqueue_in_sidekiq_or_send(job)
|
45
|
+
end
|
46
|
+
|
47
|
+
def kiqit_in(delay, queue, method, *args)
|
48
|
+
return perform_now(method, args) if plugin_disabled?
|
49
|
+
|
50
|
+
worker = Kiqit::Workers::ActiveRecord::Worker
|
51
|
+
job = Kiqit::JobCreator.new(queue, worker, self.class.name, self.id, method, *args)
|
52
|
+
enqueue_in_sidekiq_or_send(job, delay)
|
53
|
+
end
|
54
|
+
|
55
|
+
def kiqit_in!(delay, queue, method, *args)
|
56
|
+
return perform_now(method, args) if plugin_disabled?
|
57
|
+
|
58
|
+
worker = Kiqit::Workers::ActiveRecord::LoneWorker
|
59
|
+
job = Kiqit::JobCreator.new(queue, worker, self.class.name, self.id, method, *args)
|
60
|
+
enqueue_in_sidekiq_or_send(job, delay)
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
private
|
66
|
+
def loner_exists(method, args)
|
67
|
+
args = Kiqit::ArgsParser.args_to_sidekiq(args)
|
68
|
+
digest = Kiqit::PayloadHelper.get_digest(self.class.name, method, args)
|
69
|
+
|
70
|
+
return true unless Sidekiq.redis{ |i| i.get(digest).blank?}
|
71
|
+
Sidekiq.redis{|i| i.set(digest, 'EXISTS')}
|
72
|
+
|
73
|
+
return false
|
74
|
+
end
|
75
|
+
|
76
|
+
def enqueue_in_sidekiq_or_send(job, delay=nil)
|
77
|
+
job.args = Kiqit::ArgsParser.args_to_sidekiq(job.args)
|
78
|
+
job.enqueue(delay)
|
79
|
+
end
|
80
|
+
|
81
|
+
def plugin_disabled?
|
82
|
+
!Kiqit.config.enabled?
|
83
|
+
end
|
84
|
+
|
85
|
+
def perform_now(method, args)
|
86
|
+
return self.send(method, *args)
|
87
|
+
end
|
88
|
+
end
|