disc 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7e4f52b8bcd6d2c7b0648a5943c23f41c2fc71b0
4
- data.tar.gz: 45fded657cbdd9122369e9cee62a0f451fb65309
3
+ metadata.gz: 233a653ff0bf84c468fda3cbeb939259209eae64
4
+ data.tar.gz: c9f14c60f0d2dfa165eb56421d3e1f2ed0eb3c6c
5
5
  SHA512:
6
- metadata.gz: 29e37f6f7c7b706345a66699beca6513f3adb1351b61d4a6d99513a207f0798af25a59542514f1728e56254c772e0df5cbfda5cab24a10efe8071abf75b8ec79
7
- data.tar.gz: d8917b863ef3073e27ed2804174e8719d71d1021adc5c45eca79873a13988eadf9293b2f668936da140f311a204f8a94c57d216bb2a1f69d9ec2089694cfb94a
6
+ metadata.gz: 49b4e538464fddd391724150b4403bb4be4f00adddfe4a374e3e0a30c664e759615cc10ef8385f5d26592e5e0323f0d77e0e9a29f1aa8bddccddd6a321d874a8
7
+ data.tar.gz: 8e6caa1a5e2532ee85f40d97e849415cc402127e6258c83e999148c5edc673da1bb6565fa5bb5a7582f8283084dbd11d73d135e76aac14469c7b722d4df4d136
data/README.md CHANGED
@@ -23,7 +23,7 @@ Disc fills the gap between your Ruby service objects and [antirez](http://antire
23
23
  include Disc::Job
24
24
  disc queue: 'urgent'
25
25
 
26
- def self.perform(type)
26
+ def perform(type)
27
27
  # perform rather lengthy operations here.
28
28
  end
29
29
  end
@@ -94,7 +94,7 @@ Signature documentation follows:
94
94
  ## Parameters:
95
95
  #
96
96
  ## `arguments` - an optional array of arguments with which to execute
97
- # the job's `self.perform` method.
97
+ # the job's `perform` method.
98
98
  #
99
99
  # `at` - an optional named parameter specifying a moment in the
100
100
  # future in which to run the job, must respond to
@@ -142,7 +142,7 @@ Signature documentation follows:
142
142
 
143
143
  You can see [Disque's ADDJOB documentation](https://github.com/antirez/disque#addjob-queue_name-job-ms-timeout-replicate-count-delay-sec-retry-sec-ttl-sec-maxlen-count-async) for more details
144
144
 
145
- When a Disc worker process is assigned a job, it will create a new intance of the job's class and execute the `self.perform` method with whatever arguments were previously passed to `#enqueue`.
145
+ When a Disc worker process is assigned a job, it will create a new intance of the job's class and execute the `perform` method with whatever arguments were previously passed to `#enqueue`.
146
146
 
147
147
  Example:
148
148
 
@@ -151,7 +151,7 @@ class ComplexJob
151
151
  include Disc::Job
152
152
  disc queue: 'urgent'
153
153
 
154
- def self.perform(first_parameter, second_parameter)
154
+ def perform(first_parameter, second_parameter)
155
155
  # do things...
156
156
  end
157
157
  end
@@ -160,7 +160,32 @@ end
160
160
  ComplexJob.enqueue(['first argument', { second: 'argument' }])
161
161
  ```
162
162
 
163
- ### Job Status
163
+ ### Managing Jobs
164
+
165
+ Disc jobs can be managed by knowing their disque ID, this id is returned by the `#enqueue` method so you can control the job or query it's state from your application code.
166
+
167
+ ```ruby
168
+ Echoer.enqueue('test')
169
+ #=> "DIa18101491133639148a574eb30cd2e12f25dcf8805a0SQ"
170
+ ```
171
+
172
+ The disque ID is also available from within the context of an executing job, you can access it via `self.disque_id` if you wish to do things like notify Disque that a long-running job is still being executed.
173
+
174
+ ```ruby
175
+ class LongJob
176
+ include Disc::Job
177
+
178
+ def perform(first_parameter, second_parameter)
179
+ # Do things that take a while.
180
+
181
+ Disc.disque.call('WORKING', self.disque_id)
182
+
183
+ # Do more things that take a while.
184
+ end
185
+ end
186
+ ```
187
+
188
+ #### Job Status
164
189
 
165
190
  After a job is enqueued, you can check it's current status like so:
166
191
 
@@ -192,12 +217,16 @@ Disc["DIa18101491133639148a574eb30cd2e12f25dcf8805a0SQ"]
192
217
 
193
218
  This information might vary, as it's retreived from Disque via the [`SHOW`](https://github.com/antirez/disque#show-job-id) command, only `arguments` and `class` are filled in by Disc, which are added by using `Disc.deserialize` on the `body` value.
194
219
 
220
+ #### Do everything Disque can
221
+
222
+ Access to the disque ID allows us to leverage the Disque API to manage the job, you can execute Disque commands via the `Disc.disque.call()` method, see [the Disque API](https://github.com/antirez/disque#main-api) to see all the commands available.
223
+
195
224
  ### Job Serialization
196
225
 
197
226
  Job information (their arguments, and class) need to be serialized in order to be stored
198
227
  in Disque, to this end Disc uses the `Disc.serialize` and `Disc.deserialize` methods.
199
228
 
200
- By default, these methods use by default the Ruby standard library json implementation in order to serialize and deserialize job data, this has a few implications:
229
+ By default, these methods use the Ruby standard library json implementation in order to serialize and deserialize job data, this has a few implications:
201
230
 
202
231
  1. Arguments passed to a job's `#enqueue` method need to be serializable by `Disc.serialize` and parsed back by `Disc.deserialize`, so by default you can't pass complex Ruby objects like a `user` model, instead, pass `user.id`, and use that from your job code.
203
232
 
@@ -317,7 +346,7 @@ end
317
346
  class CluJob < ActiveJob::Base
318
347
  queue_as :urgent
319
348
 
320
- def self.perform(*args)
349
+ def perform(*args)
321
350
  # Try to take over The Grid here...
322
351
  end
323
352
  end
@@ -4,7 +4,7 @@ class Echoer
4
4
  include Disc::Job
5
5
  disc queue: 'test'
6
6
 
7
- def self.perform(first, second, third)
7
+ def perform(first, second, third)
8
8
  puts "First: #{ first }, Second: #{ second }, Third: #{ third }"
9
9
  end
10
10
  end
@@ -10,7 +10,7 @@ class Failer
10
10
  include Disc::Job
11
11
  disc queue: 'test'
12
12
 
13
- def self.perform(string)
13
+ def perform(string)
14
14
  raise string
15
15
  end
16
16
  end
@@ -4,7 +4,7 @@ class Greeter
4
4
  include Disc::Job
5
5
  disc queue: 'test_medium'
6
6
 
7
- def self.perform(string)
7
+ def perform(string)
8
8
  $stdout.puts(string)
9
9
  end
10
10
  end
@@ -0,0 +1,10 @@
1
+ require 'disc'
2
+
3
+ class Identifier
4
+ include Disc::Job
5
+ disc queue: 'test'
6
+
7
+ def perform
8
+ $stdout.puts("Working with Disque ID: #{ self.disque_id }")
9
+ end
10
+ end
@@ -1,7 +1,7 @@
1
1
  class Returner
2
2
  include Disc::Job
3
3
 
4
- def self.perform(argument)
4
+ def perform(argument)
5
5
  return argument
6
6
  end
7
7
  end
@@ -73,7 +73,7 @@ class Disc
73
73
  # * An instance of the given job class
74
74
  # * An array of arguments to pass to the job's `#perorm` class.
75
75
  #
76
- def self.load_job(serialized_job)
76
+ def self.load_job(serialized_job, disque_id = nil)
77
77
  begin
78
78
  job_data = Disc.deserialize(serialized_job)
79
79
  rescue => err
@@ -86,7 +86,14 @@ class Disc
86
86
  raise Disc::UnknownJobClassError.new(err)
87
87
  end
88
88
 
89
- return [job_class, job_data['arguments']]
89
+ begin
90
+ job_instance = job_class.new
91
+ job_instance.disque_id = disque_id
92
+ rescue => err
93
+ raise Disc::NonJobClassError.new(err)
94
+ end
95
+
96
+ return [job_instance, job_data['arguments']]
90
97
  end
91
98
  end
92
99
 
@@ -1,6 +1,7 @@
1
1
  class Disc
2
2
  class Error < StandardError; end
3
3
 
4
- class UnknownJobClassError < Error; end
5
- class NonParsableJobError < Error; end
4
+ class UnknownJobClassError < Error; end
5
+ class NonParsableJobError < Error; end
6
+ class NonJobClassError < Error; end
6
7
  end
@@ -1,4 +1,5 @@
1
1
  module Disc::Job
2
+ attr_accessor :disque_id
2
3
 
3
4
  def self.included(base)
4
5
  base.extend(ClassMethods)
@@ -26,6 +27,10 @@ module Disc::Job
26
27
  @queue || Disc.default_queue
27
28
  end
28
29
 
30
+ def perform(arguments)
31
+ self.new.perform(*arguments)
32
+ end
33
+
29
34
  ## Disc's `#enqueue` is the main user-facing method of a Disc job, it
30
35
  # enqueues a job with a given set of arguments in Disque, so it can be
31
36
  # picked up by a Disc worker process.
@@ -1,3 +1,3 @@
1
1
  class Disc
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -52,15 +52,15 @@ class Disc::Worker
52
52
  jobs = disque.fetch(from: queues, timeout: timeout, count: count)
53
53
  Array(jobs).each do |queue, msgid, serialized_job|
54
54
  begin
55
- job_class, arguments = Disc.load_job(serialized_job)
56
- job_class.perform(*arguments)
55
+ job_instance, arguments = Disc.load_job(serialized_job, msgid)
56
+ job_instance.perform(*arguments)
57
57
  disque.call('ACKJOB', msgid)
58
- $stdout.puts("Completed #{ job_class.name } id #{ msgid }")
58
+ $stdout.puts("Completed #{ job_instance.class.name } id #{ msgid }")
59
59
  rescue => err
60
60
  Disc.on_error(err, {
61
61
  disque_id: msgid,
62
62
  queue: queue,
63
- class: defined?(job_class) ? job_class.name : '',
63
+ class: defined?(job_instance) ? job_instance.class.name : '',
64
64
  arguments: defined?(arguments) ? arguments : []
65
65
  })
66
66
  end
@@ -44,9 +44,9 @@ scope do
44
44
  { class: 'Echoer', arguments: ['one argument', { random: 'data' }, 3] }
45
45
  )
46
46
 
47
- job_class, arguments = Disc.load_job(serialized_job)
47
+ job_instance, arguments = Disc.load_job(serialized_job)
48
48
 
49
- assert_equal Echoer, job_class
49
+ assert_equal Echoer, job_instance.class
50
50
  assert arguments.is_a?(Array)
51
51
  assert_equal 3, arguments.count
52
52
  assert_equal 'one argument', arguments.first
@@ -5,6 +5,7 @@ require 'timeout'
5
5
 
6
6
  require_relative '../examples/echoer'
7
7
  require_relative '../examples/failer'
8
+ require_relative '../examples/identifier'
8
9
 
9
10
  prepare do
10
11
  Disc.disque_timeout = 1 # 1ms so we don't wait at all.
@@ -35,14 +36,12 @@ scope do
35
36
 
36
37
  run('QUEUES=test ruby -Ilib bin/disc -r ./examples/failer') do |cout, pid|
37
38
  output = Timeout.timeout(1) { cout.take(5) }
38
- jobs = Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1)
39
- assert jobs.nil?
40
-
41
39
  assert output.grep(/<insert error reporting here>/).any?
42
40
  assert output.grep(/this can only end positively/).any?
43
41
  assert output.grep(/Failer/).any?
44
42
 
45
43
  assert is_running?(pid)
44
+ assert_equal 0, Disc.qlen(Failer.queue)
46
45
  end
47
46
  end
48
47
 
@@ -51,9 +50,19 @@ scope do
51
50
 
52
51
  run('QUEUES=test ruby -Ilib bin/disc -r ./examples/echoer') do |cout, pid|
53
52
  output = Timeout.timeout(1) { cout.take(3) }
54
- jobs = Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1)
55
- assert jobs.nil?
56
53
  assert output.grep(/First: one argument, Second: {"random"=>"data"}, Third: 3/).any?
54
+ assert_equal 0, Disc.qlen(Echoer.queue)
55
+ end
56
+ end
57
+
58
+ test 'running jobs have access to their Disque job ID' do
59
+ disque_id = Identifier.enqueue
60
+
61
+ run('QUEUES=test ruby -Ilib bin/disc -r ./examples/identifier') do |cout, pid|
62
+ output = Timeout.timeout(1) { cout.take(3) }
63
+ assert output.grep(/Working with Disque ID: #{ disque_id }/).any?
64
+
65
+ assert_equal 0, Disc.qlen(Identifier.queue)
57
66
  end
58
67
  end
59
68
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: disc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - pote
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-10 00:00:00.000000000 Z
11
+ date: 2016-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: disque
@@ -61,6 +61,7 @@ files:
61
61
  - examples/echoer.rb
62
62
  - examples/failer.rb
63
63
  - examples/greeter.rb
64
+ - examples/identifier.rb
64
65
  - examples/returner.rb
65
66
  - lib/active_job/queue_adapters/disc_adapter.rb
66
67
  - lib/disc.rb