class Abid::State

Constants

FAILED
RUNNING
STATES
SUCCESSED

Public Class Methods

deserialize(bytes) click to toggle source
# File lib/abid/state.rb, line 53
def deserialize(bytes)
  YAML.load(bytes)
end
find(task) click to toggle source
# File lib/abid/state.rb, line 16
def find(task)
  synchronize { @cache[task.object_id] ||= new(task) }
end
list(pattern: nil, started_before: nil, started_after: nil) click to toggle source
# File lib/abid/state.rb, line 20
def list(pattern: nil, started_before: nil, started_after: nil)
  dataset = Rake.application.database[:states]

  dataset = dataset.where { start_time < started_before } if started_before
  dataset = dataset.where { start_time > started_after } if started_after
  dataset = dataset.order(:start_time)

  dataset.map do |record|
    next if pattern && record[:name] !~ pattern
    {
      id: record[:id],
      name: record[:name],
      params: deserialize(record[:params]),
      state: STATES[record[:state]],
      start_time: record[:start_time],
      end_time: record[:end_time]
    }
  end.compact
end
new(task) click to toggle source
# File lib/abid/state.rb, line 60
def initialize(task)
  @task = task
  @record = nil
  @started = false
  reload
end
revoke(id) click to toggle source
# File lib/abid/state.rb, line 40
def revoke(id)
  db = Rake.application.database
  db.transaction do
    running = db[:states].where(id: id, state: RUNNING).count > 0
    fail 'task is now running' if running
    db[:states].where(id: id).delete
  end
end
serialize(params) click to toggle source
# File lib/abid/state.rb, line 49
def serialize(params)
  YAML.dump(params)
end

Public Instance Methods

assume() click to toggle source
# File lib/abid/state.rb, line 120
def assume
  fail 'cannot revoke volatile task' if disabled?

  database.transaction do
    reload
    fail 'task is now running' if running?

    new_state = {
      state: SUCCESSED,
      start_time: Time.now,
      end_time: Time.now
    }

    if @record
      dataset.where(id: @record[:id]).update(new_state)
      @record = @record.merge(new_state)
    else
      id = dataset.insert(
        digest: digest,
        name: @task.name,
        params: serialize(@task.params),
        **new_state
      )
      @record = { id: id, **new_state }
    end
  end
end
database() click to toggle source
# File lib/abid/state.rb, line 67
def database
  Rake.application.database
end
dataset() click to toggle source
# File lib/abid/state.rb, line 71
def dataset
  database[:states]
end
digest() click to toggle source
# File lib/abid/state.rb, line 189
def digest
  Digest::MD5.hexdigest(@task.name + "\n" + serialize(@task.params))
end
disabled?() click to toggle source
# File lib/abid/state.rb, line 75
def disabled?
  @task.volatile? || Rake.application.options.disable_state
end
failed?() click to toggle source
# File lib/abid/state.rb, line 112
def failed?
  state == FAILED
end
finish(error = nil) click to toggle source
# File lib/abid/state.rb, line 180
def finish(error = nil)
  return if disabled? || preview?
  return unless @record
  return unless @started
  state = error ? FAILED : SUCCESSED
  dataset.where(id: @record[:id]).update(state: state, end_time: Time.now)
  reload
end
id() click to toggle source
# File lib/abid/state.rb, line 96
def id
  @record[:id] if @record
end
not_found?() click to toggle source
# File lib/abid/state.rb, line 116
def not_found?
  !disabled? && @record.nil?
end
preview?() click to toggle source
# File lib/abid/state.rb, line 79
def preview?
  Rake.application.options.dryrun || Rake.application.options.preview
end
reload() click to toggle source
# File lib/abid/state.rb, line 83
def reload
  return if disabled?

  if @record
    id = @record[:id]
    @record = dataset.where(id: id).first
  else
    @record = dataset.where(digest: digest).to_a.find do |r|
      [@task.name, @task.params].eql? [r[:name], deserialize(r[:params])]
    end
  end
end
running?() click to toggle source
# File lib/abid/state.rb, line 104
def running?
  state == RUNNING
end
start() click to toggle source
# File lib/abid/state.rb, line 148
def start
  return true if disabled? || preview?

  database.transaction do
    reload

    fail AbidErrorTaskAlreadyRunning if running?

    new_state = {
      state: RUNNING,
      start_time: Time.now,
      end_time: nil
    }

    if @record
      dataset.where(id: @record[:id]).update(new_state)
      @record = @record.merge(new_state)
    else
      id = dataset.insert(
        digest: digest,
        name: @task.name,
        params: serialize(@task.params),
        **new_state
      )
      @record = { id: id, **new_state }
    end

    @started = true
    true
  end
end
state() click to toggle source
# File lib/abid/state.rb, line 100
def state
  @record[:state] if @record
end
successed?() click to toggle source
# File lib/abid/state.rb, line 108
def successed?
  state == SUCCESSED
end