kiqit 0.0.1 → 1.3.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.
- 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
|
+
[](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
|