Class: Backnob::Worker

Inherits:
Object
  • Object
show all
Includes:
DRb::DRbObservable
Defined in:
lib/backnob/worker.rb

Overview

Worker class. Workers should inherit from this class and implement the execute method.

Example of a simple worker:

class SimpleWorker < Backnob::Worker
  def execute
    contents = File.read(@options[:file])
    File.open('simple.txt', 'a') do |file|
      file.write contents
    end

    results(:size, File.size('simple.txt'))
  end
end

Usage:

client = Backnob::Client.new
client.add_worker('simple.rb')
key = client.create_worker('simple', :file => '/tmp/to_be_read.txt')
while !client.results(key, :finished)
  sleep 1
end

unless client.results(key, :error)
  puts "File length is now: #{client.results(key, :size)}"
else
  puts client.results(key, :error).to_s
end

Worker adds the key :running to the results automatically and sets it to true when it starts.

If an error occurs during execution the worker will place the error object into the results under the key :error.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, options = {}) ⇒ Worker

Server creates a new worker passing its key and any user options as a hash



78
79
80
81
82
83
84
85
# File 'lib/backnob/worker.rb', line 78

def initialize(key, options = {})
  @options = options
  @results = {}
  @results.extend(MonitorMixin)
  
  @wqueue = Queue.new
  enqueue(key, options)
end

Instance Attribute Details

#keyObject (readonly)

Returns the value of attribute key.



52
53
54
# File 'lib/backnob/worker.rb', line 52

def key
  @key
end

Class Method Details

.define_attr_method(name, value) ⇒ Object

:nodoc:



54
55
56
57
58
59
60
61
62
63
64
# File 'lib/backnob/worker.rb', line 54

def self.define_attr_method(name, value) # :nodoc:
  class_eval do      
    define_method(name) do
      value
    end
  end
  
  self.singleton_class.send :define_method, name do
    value
  end
end

.define_class_attr(name, default) ⇒ Object

:nodoc:



66
67
68
69
70
71
# File 'lib/backnob/worker.rb', line 66

def self.define_class_attr(name, default) # :nodoc:
  define_attr_method name, default
  self.singleton_class.send :define_method, name do |value|
    define_attr_method name, value
  end
end

Instance Method Details

#enqueue(key, options = {}) ⇒ Object



92
93
94
# File 'lib/backnob/worker.rb', line 92

def enqueue(key, options = {})
  @wqueue << [key, options]
end

#loggerObject

Access to the logger



88
89
90
# File 'lib/backnob/worker.rb', line 88

def logger
  @logger ||= Logger.new($stdout)
end

#results(key = nil, value = nil) ⇒ Object

Get or set results. Workers should access results through this method as it is synchronized.

Results are marshalled back to the client, so if you are passing non-standard classes be sure to require the appropriate files on the client side.



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/backnob/worker.rb', line 140

def results(key = nil,value = nil)      
  res = nil

  @results.synchronize do
    @results[@key] ||= {}
    
    if key.nil?
      res = @results[@key].dup
    elsif value.nil?      
      res = @results[@key][key]
    else
      if value != @results[@key][key]
        @results[@key][key] = value
        changed(true) # I've changed

        # Marshal results into string
        # for some reason marshal doesn't like hash, so
        # convert to array and convert back on server side
        obo = ::Marshal.dump([@key, key, value])
        notify_observers(obo)
      end
    end
  end

  res
end

#startObject

Start this worker. Starts a new thread and calls execute for work to be performed.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/backnob/worker.rb', line 98

def start
  @thread = Thread.new do
    Thread.pass      
    @running = true
            
    if rails
      require 'config/environment'
      ActiveRecord::Base.logger = logger
    end
    
    begin
      # Get work item off queue
      @key, @options = @wqueue.pop                      
      logger.debug "Starting #{self.class.name} with key #{@key}"
      
      begin
        execute unless @key == :stop
      rescue Exception => e
        results(:error, e)
      ensure
        results(:finished, true)
        logger.debug "Finished #{self.class.name} with key #{@key}"
      end
    end while @running && self.single
    
    logger.debug "Worker #{self.class.name} exiting"
    exit!
  end
end

#stopObject

Stop this worker.



129
130
131
132
# File 'lib/backnob/worker.rb', line 129

def stop
  @running = false
  @wqueue << [:stop, {}]
end