Class: StalkClimber::Job

Inherits:
Beaneater::Job
  • Object
show all
Defined in:
lib/stalk_climber/job.rb

Constant Summary collapse

FRESH_ATTRIBUTES =

Attributes that are retrieved each request by default

%w[delay pri state time-left]
CACHED_ATTRIBUTES =

Attributes that return cached values by default

%w[age buries kicks releases reserves timeouts ttr tube]
STATS_ATTRIBUTES =

All attributes available via a job’s stats

(CACHED_ATTRIBUTES + FRESH_ATTRIBUTES).sort!
STATS_METHODS =

Lookup table of which method to call to retrieve each stat

Hash[
  STATS_ATTRIBUTES.zip(STATS_ATTRIBUTES.map {|stat| stat.gsub(/-/, '_')})
]

Instance Method Summary collapse

Constructor Details

#initialize(job_data) ⇒ Job

:call-seq:

new(job_data) => Job

Initializes a Job instance using job_data which should be the Beaneater response to either a put, peek, or stats-job command. Other Beaneater responses are not supported.

No single beanstalk command provides all the data an instance might need, so as more information is required, additional calls are made to beanstalk. For example, accessing both a job’s tube and its body requires both a peek and stats-job call.

Put provides only the ID of the job and as such yields the least informed instance. Both a peek and stats-job call may be required to retrieve anything but the ID of the instance

Peek and reserve provide the ID and body of the job. A stats-job call may be required to access anything but the ID or body of the job.

Stats-job provides the most information about the job, but lacks the crtical component of the job body. As such, a peek call would be required to access the body of the job.

reserve_response = connection.transmit('reserve')
StalkClimber::Job.new(reserve_response)
  #=> #<StalkClimber::Job id=1 body="Work to be done">


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/stalk_climber/job.rb', line 100

def initialize(job_data)
  case job_data[:status]
  when 'INSERTED' # put
    @id = job_data[:id].to_i
    @body = @stats = nil
  when 'FOUND', 'RESERVED' # peek, reserve
    @id = job_data[:id].to_i
    @body = job_data[:body]
    @stats = nil
  when 'OK' # stats-job
    @stats = Beaneater::StatStruct.from_hash(job_data[:body])
    @id = @stats.id.to_i
    @body = nil
  else
    raise RuntimeError, "Unexpected job status: #{job_data[:status]}"
  end
  @status = job_data[:status]
  @connection = job_data[:connection]
  # Don't set @reserved to force lookup each time to handle job TTR expiration
end

Instance Method Details

#bodyObject

:call-seq:

body() => String

Returns or fetches the body of the job. If not already present the body of the job is obtained via the peek command.

job = StalkClimber::Job.new(connection.transmit('reserve'))
job.body
  #=> "Work to be done"


35
36
37
# File 'lib/stalk_climber/job.rb', line 35

def body
  return @body ||= connection.transmit("peek #{id}")[:body]
end

#deleteObject

:call-seq:

delete() => Hash{Symbol => String,Integer}

Tries to delete the job from beanstalk. Returns the Beanstalkd response for the command. Raises Beaneater::NotFoundError if the job could not be found.

job = StalkClimber::Job.new(connection.transmit('reserve'))
job.delete
  #=> {:status=>"DELETED", :body=>nil, :connection=>#<Beaneater::Connection host="localhost" port=11300>}


49
50
51
52
53
54
55
# File 'lib/stalk_climber/job.rb', line 49

def delete
  result = super
  @status = 'DELETED'
  @stats = nil
  @body = nil
  return result
end

#exists?Boolean

:call-seq:

exists?() => Boolean

Determines if a job exists by retrieving stats for the job. If Beaneater can’t find the job then it does not exist and false is returned. The stats command is used because it will return a response of a near constant size, whereas, depending on the job, the peek command could return a much larger response. Rather than waste the trip to the server, stats are updated each time the method is called.

job = StalkClimber::Job.new(connection.transmit('reserve'))
job.exists?
  #=> true
job.delete
job.exists?
  #=> false

Returns:

  • (Boolean)


73
74
75
# File 'lib/stalk_climber/job.rb', line 73

def exists?
  return @status == 'DELETED' ? false : super
end

#stats(force_refresh = true) ⇒ Object

:call-seq:

stats(force_refresh = true) => Beaneater::StatStruct

Returns or retrieves stats for the job. Optionally, a retrieve may be forced by passing a non-false value for force_refresh

job = StalkClimber::Job.new(peek_response)
job.stats
  #=> #<Beaneater::StatStruct id=2523, tube="stalk_climber", state="ready", pri=0, age=25, delay=0, ttr=120, time_left=0, file=0, reserves=0, timeouts=0, releases=0, buries=0, kicks=0>


131
132
133
134
135
136
# File 'lib/stalk_climber/job.rb', line 131

def stats(force_refresh = true)
  if @stats.nil? || force_refresh
    @stats = super()
  end
  return @stats
end

#to_hObject

:call-seq:

to_h() => Hash

Returns a hash of all job attributes derived from updated stats

job = StalkClimber::Job.new(peek_response)
job.to_h
  #=> {"age"=>144, "body"=>"Work to be done", "buries"=>0, "connection"=>#<Beaneater::Connection host="localhost" port=11300>, "delay"=>0, "id"=>2523, "kicks"=>0, "pri"=>0, "releases"=>0, "reserves"=>0, "state"=>"ready", "time-left"=>0, "timeouts"=>0, "ttr"=>120, "tube"=>"stalk_climber"}


147
148
149
150
151
152
# File 'lib/stalk_climber/job.rb', line 147

def to_h
  stats
  stats_pairs = STATS_METHODS.map { |stat, method_name| [stat, stats(false)[method_name]]}
  stats_pairs.concat([['body', body], ['connection', connection], ['id', id]]).sort_by!(&:first)
  return Hash[stats_pairs]
end

#to_sObject Also known as: inspect

:call-seq:

to_s() => String

Returns string representation of job

job = StalkClimber::Job.new(peek_response)
job.to_s
  #=> #<StalkClimber::Job id=1 body="Work to be done">


163
164
165
# File 'lib/stalk_climber/job.rb', line 163

def to_s
  "#<StalkClimber::Job id=#{id} body=#{body.inspect}>"
end