Class: Batchy::Batch

Inherits:
ActiveRecord::Base
  • Object
show all
Extended by:
StateMachine::MacroMethods
Defined in:
lib/batchy/batch.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Batch

Set up callback queues and states



62
63
64
65
# File 'lib/batchy/batch.rb', line 62

def initialize *args
  create_callback_queues
  super
end

Instance Attribute Details

#ensure_callbacksObject (readonly)

Returns the value of attribute ensure_callbacks.



9
10
11
# File 'lib/batchy/batch.rb', line 9

def ensure_callbacks
  @ensure_callbacks
end

#failure_callbacksObject (readonly)

Returns the value of attribute failure_callbacks.



7
8
9
# File 'lib/batchy/batch.rb', line 7

def failure_callbacks
  @failure_callbacks
end

#ignore_callbacksObject (readonly)

Returns the value of attribute ignore_callbacks.



10
11
12
# File 'lib/batchy/batch.rb', line 10

def ignore_callbacks
  @ignore_callbacks
end

#success_callbacksObject (readonly)

Returns the value of attribute success_callbacks.



8
9
10
# File 'lib/batchy/batch.rb', line 8

def success_callbacks
  @success_callbacks
end

Class Method Details

.expiredObject

Return all expired batches that are still running



56
57
58
# File 'lib/batchy/batch.rb', line 56

def expired
  where('expire_at < ? and state = ?', DateTime.now, 'running')
end

Instance Method Details

#already_runningObject

Is there batch with the same guid already running?



68
69
70
71
72
# File 'lib/batchy/batch.rb', line 68

def already_running
  return false if guid.nil?

  duplicate_batches.count > 0
end

#clear_zombiesObject

Removes duplicate batches that are stuck in a running state



76
77
78
79
80
81
82
83
# File 'lib/batchy/batch.rb', line 76

def clear_zombies
  duplicate_batches(:limit_to_current_host => true).each do | dup |
    if not dup.process_running?
      dup.error = Batchy::Error.new("Process has died, moving to a finished state")
      dup.finish!
    end
  end
end

#duplicate_batches(*args) ⇒ Object

Find all batches with the same guid that are running.

limit_to_current_host

This option limit duplicate batches to the
current host.
Default: false

Raises:



93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/batchy/batch.rb', line 93

def duplicate_batches *args
  options = args.extract_options!
  options.reverse_merge! :limit_to_current_host => false

  raise Batchy::Error, "Can not check for duplicate batches on nil guid" if guid.nil?
  rel = self.class.where(:guid => guid, :state => "running")

  if options[:limit_to_current_host]
    rel = rel.where(:hostname => Socket.gethostname)
  end
  return rel if new_record?

  rel.where("id <> ?", id)
end

#errorObject

Conversely, the backtrace is added to the error after a read



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/batchy/batch.rb', line 117

def error
  err = read_attribute(:error)
  return err if err.blank?

  backtrace = read_attribute(:backtrace)
  if err.respond_to?(:set_backtrace)
    err.set_backtrace(backtrace) 
  else
    def err.backtrace
      nil
    end
  end

  err
end

#error=(err) ⇒ Object

When serializing an exception, the YAML library does not save the backtrace. To fix this, we’re saving both the error and backtrace when the error is saved



111
112
113
114
# File 'lib/batchy/batch.rb', line 111

def error=(err)
  write_attribute(:error, err)
  write_attribute(:backtrace, err.backtrace) if err.respond_to?(:backtrace)
end

#expired?Boolean

Is this batch expired

Returns:

  • (Boolean)


134
135
136
# File 'lib/batchy/batch.rb', line 134

def expired?
  expire_at < DateTime.now && state == 'running'
end

#has_errorsObject

Does this batch have errors?



139
140
141
# File 'lib/batchy/batch.rb', line 139

def has_errors
  error?
end

#invalid_duplicationObject

Is this an unwanted duplicate process?



144
145
146
# File 'lib/batchy/batch.rb', line 144

def invalid_duplication
  !Batchy.configure.allow_duplicates && already_running
end

#killObject

Issues a SIGTERM to the process running this batch



149
150
151
152
153
# File 'lib/batchy/batch.rb', line 149

def kill
  return false unless hostname == ::Socket.gethostname

  Process.kill('TERM', pid)
end

#kill!Object

Issue a SIGKILL to the process running this batch BE CAREFUL! This will kill your application or server if this batch has the same PID.



158
159
160
161
162
# File 'lib/batchy/batch.rb', line 158

def kill!
  return false unless hostname == ::Socket.gethostname
  
  Process.kill('KILL', pid)
end

#on_ensure(*args, &block) ⇒ Object

Adds a callback that runs no matter what the exit state of the batchy block



166
167
168
169
170
171
172
# File 'lib/batchy/batch.rb', line 166

def on_ensure *args, &block
  if block_given?
    @ensure_callbacks << block
  else
    @ensure_callbacks << args.shift
  end
end

#on_failure(*args, &block) ⇒ Object

Add a callback to run on failure of the batch



176
177
178
179
180
181
182
# File 'lib/batchy/batch.rb', line 176

def on_failure *args, &block
  if block_given?
    @failure_callbacks << block
  else
    @failure_callbacks << args.shift
  end
end

#on_ignore(*args, &block) ⇒ Object

Adds a callback that runs if the process is a duplicate



186
187
188
189
190
191
192
# File 'lib/batchy/batch.rb', line 186

def on_ignore *args, &block
  if block_given?
    @ignore_callbacks << block
  else
    @ignore_callbacks << args.shift
  end
end

#on_success(*args, &block) ⇒ Object

Add a callback to run on successful completion of the batch



196
197
198
199
200
201
202
# File 'lib/batchy/batch.rb', line 196

def on_success *args, &block
  if block_given?
    @success_callbacks << block
  else
    @success_callbacks << args.shift
  end
end

#process_running?Boolean

Checks to see if the process attached to this batch is active

Returns:

  • (Boolean)

Raises:



206
207
208
209
210
# File 'lib/batchy/batch.rb', line 206

def process_running?
  raise Batchy::Error, 'Current host does not match the host running the batch' unless Socket.gethostname == hostname

  not Sys::ProcTable.ps(pid).blank?
end

#run_ensure_callbacksObject

:nodoc:



213
214
215
216
217
218
219
220
# File 'lib/batchy/batch.rb', line 213

def run_ensure_callbacks
  Batchy.configure.global_ensure_callbacks.each do | ec |
    ec.call(self)
  end
  ensure_callbacks.each do | ec |
    ec.call(self)
  end
end

#run_failure_callbacksObject

:nodoc:



243
244
245
246
247
248
249
250
# File 'lib/batchy/batch.rb', line 243

def run_failure_callbacks
  Batchy.configure.global_failure_callbacks.each do | fc |
    fc.call(self)
  end
  failure_callbacks.each do | fc |
    fc.call(self)
  end
end

#run_ignore_callbacksObject

:nodoc:



223
224
225
226
227
228
229
230
# File 'lib/batchy/batch.rb', line 223

def run_ignore_callbacks
  Batchy.configure.global_ignore_callbacks.each do | ic |
    ic.call(self)
  end
  ignore_callbacks.each do | ic |
    ic.call(self)
  end
end

#run_success_callbacksObject

:nodoc:



233
234
235
236
237
238
239
240
# File 'lib/batchy/batch.rb', line 233

def run_success_callbacks
  Batchy.configure.global_success_callbacks.each do | sc |
    sc.call(self)
  end
  success_callbacks.each do | sc |
    sc.call(self)
  end
end