Class: Resque::Status

Inherits:
Hash
  • Object
show all
Extended by:
Helpers
Defined in:
lib/resque/status.rb

Overview

Resque::Status is a Hash object that has helper methods for dealing with the common status attributes. It also has a number of class methods for creating/updating/retrieving status objects from Redis

Constant Summary collapse

VERSION =
'0.1.5'
STATUSES =
%w{queued working completed failed killed}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Status

Create a new Resque::Status object. If multiple arguments are passed it is assumed the first argument is the UUID and the rest are status objects. All arguments are subsequentily merged in order. Strings are assumed to be messages.



159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/resque/status.rb', line 159

def initialize(*args)
  super nil
  base_status = {
    'time' => Time.now.to_i,
    'status' => 'queued'
  }
  base_status['uuid'] = args.shift if args.length > 1
  status_hash = args.inject(base_status) do |final, m|
    m = {'message' => m} if m.is_a?(String)
    final.merge(m || {})
  end
  self.replace(status_hash)
end

Class Method Details

.clearObject



41
42
43
44
45
46
# File 'lib/resque/status.rb', line 41

def self.clear
  status_ids.each do |id|
    redis.del(status_key(id))
    redis.zrem(set_key, id)
  end
end

.create(message = nil) ⇒ Object

Create a status, generating a new UUID, passing the message to the status Returns the UUID of the new status.



16
17
18
19
20
21
22
# File 'lib/resque/status.rb', line 16

def self.create(message = nil)
  uuid = generate_uuid
  set(uuid, message)
  redis.zadd(set_key, Time.now.to_i, uuid)
  redis.zremrangebyscore(set_key, 0, Time.now.to_i - @expire_in) if @expire_in
  uuid
end

.expire_inObject

The time in seconds that jobs and statuses should expire from Redis (after the last time they are touched/updated)



95
96
97
# File 'lib/resque/status.rb', line 95

def self.expire_in
  @expire_in
end

.expire_in=(seconds) ⇒ Object

Set the expire_in time in seconds



100
101
102
# File 'lib/resque/status.rb', line 100

def self.expire_in=(seconds)
  @expire_in = seconds.nil? ? nil : seconds.to_i
end

.generate_uuidObject



120
121
122
# File 'lib/resque/status.rb', line 120

def self.generate_uuid
  UUID.generate(:compact)
end

.get(uuid) ⇒ Object

Get a status by UUID. Returns a Resque::Status



25
26
27
28
# File 'lib/resque/status.rb', line 25

def self.get(uuid)
  val = redis.get(status_key(uuid))
  val ? Resque::Status.new(uuid, decode(val)) : nil
end

.hash_accessor(name, options = {}) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/resque/status.rb', line 124

def self.hash_accessor(name, options = {})
  options[:default] ||= nil 
  coerce = options[:coerce] ? ".#{options[:coerce]}" : ""
  module_eval <<-EOT
  def #{name}
    value = (self['#{name}'] ? self['#{name}']#{coerce} : #{options[:default].inspect})
    yield value if block_given?
    value
  end

  def #{name}=(value)
    self['#{name}'] = value
  end

  def #{name}?
    !!self['#{name}']
  end
  EOT
end

.kill(uuid) ⇒ Object

Kill the job at UUID on its next iteration this works by adding the UUID to a kill list (a.k.a. a list of jobs to be killed. Each iteration the job checks if it should be killed by calling tick or at. If so, it raises a Resque::JobWithStatus::Killed error and sets the status to ‘killed’.



74
75
76
# File 'lib/resque/status.rb', line 74

def self.kill(uuid)                 
  redis.sadd(kill_key, uuid)
end

.kill_idsObject

Return the UUIDs of the jobs on the kill list



84
85
86
# File 'lib/resque/status.rb', line 84

def self.kill_ids
  redis.smembers(kill_key)
end

.kill_keyObject



112
113
114
# File 'lib/resque/status.rb', line 112

def self.kill_key
  "_kill"
end

.killed(uuid) ⇒ Object

Remove the job at UUID from the kill list



79
80
81
# File 'lib/resque/status.rb', line 79

def self.killed(uuid)
  redis.srem(kill_key, uuid)
end

.logger(uuid, options = {}) ⇒ Object

returns a Redisk::Logger scoped to the UUID. Any options passed are passed to the logger initialization.

Ensures that Redisk is logging to the same Redis connection as Resque.



52
53
54
55
# File 'lib/resque/status.rb', line 52

def self.logger(uuid, options = {})
  Redisk.redis = redis
  Redisk::Logger.new(logger_key(uuid), options)
end

.logger_key(uuid) ⇒ Object



116
117
118
# File 'lib/resque/status.rb', line 116

def self.logger_key(uuid)
  "_log:#{uuid}"
end

.set(uuid, *messages) ⇒ Object

set a status by UUID. messages can be any number of stirngs or hashes that are merged in order to create a single status.



32
33
34
35
36
37
38
39
# File 'lib/resque/status.rb', line 32

def self.set(uuid, *messages)
  val = Resque::Status.new(uuid, *messages)
  redis.set(status_key(uuid), encode(val))
  if expire_in
    redis.expire(status_key(uuid), expire_in) 
  end
  val
end

.set_keyObject



108
109
110
# File 'lib/resque/status.rb', line 108

def self.set_key
  "_statuses"
end

.should_kill?(uuid) ⇒ Boolean

Check whether a job with UUID is on the kill list

Returns:

  • (Boolean)


89
90
91
# File 'lib/resque/status.rb', line 89

def self.should_kill?(uuid)
  redis.sismember(kill_key, uuid)
end

.status_ids(num = -1)) ⇒ Object

Return the num most recent status/job UUIDs in reverse chronological order.



66
67
68
# File 'lib/resque/status.rb', line 66

def self.status_ids(num = -1)
  redis.zrevrange(set_key, 0, num) || []
end

.status_key(uuid) ⇒ Object



104
105
106
# File 'lib/resque/status.rb', line 104

def self.status_key(uuid)
  "status:#{uuid}"
end

.statuses(num = -1)) ⇒ Object

Return num Resque::Status objects in reverse chronological order. By default returns the entire set.



59
60
61
62
63
# File 'lib/resque/status.rb', line 59

def self.statuses(num = -1)
  status_ids(num).collect do |id|
    get(id)
  end.compact
end

Instance Method Details

#inspectObject



217
218
219
# File 'lib/resque/status.rb', line 217

def inspect
  "#<Resque::Status #{super}>"
end

#jsonObject

Return a JSON representation of the current object.



211
212
213
214
215
# File 'lib/resque/status.rb', line 211

def json
  h = self.dup
  h['pct_complete'] = pct_complete
  self.class.encode(h)
end

#killable?Boolean

Can the job be killed? ‘failed’, ‘completed’, and ‘killed’ jobs cant be killed (for pretty obvious reasons)

Returns:

  • (Boolean)


200
201
202
# File 'lib/resque/status.rb', line 200

def killable?
  !['failed', 'completed', 'killed'].include?(self.status)
end

#pct_completeObject

calculate the % completion of the job based on status, num and total



175
176
177
178
179
180
181
182
183
184
# File 'lib/resque/status.rb', line 175

def pct_complete
  case status
  when 'completed' then 100
  when 'queued' then 0
  when 'failed' then 100
  else
    t = (total == 0 || total.nil?) ? 1 : total
    (((num || 0).to_f / t.to_f) * 100).to_i
  end
end

#timeObject

Return the time of the status initialization. If set returns a Time object, otherwise returns nil



188
189
190
# File 'lib/resque/status.rb', line 188

def time
  time? ? Time.at(self['time']) : nil
end

#to_json(*args) ⇒ Object



205
206
207
# File 'lib/resque/status.rb', line 205

def to_json(*args)
  json
end