Class: Loops::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/loops/base.rb

Overview

Base class for all loop processes.

To create a new loop just inherit this class and override the #run method (see example below).

In most cases it’s a good idea to re-run your loop periodically. In this case your process will free all unused memory to the system, and all leaked resources (yes, it’s real life).

Examples:

class MySuperLoop < Loops::Base
  def self.check_dependencies
    gem 'tinder', '=1.3.1'
  end

  def run
    1000.times do
      if shutdown?
        info("Shutting down!")
        exit(0)
      end

      unless item = UploadItems.get_next
        sleep(config['sleep_time'])
        next
      end

      item.perform_upload
    end
  end
end

Direct Known Subclasses

Queue

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pm, name, config) ⇒ Base

Initializes a new instance of loop.

Parameters:

  • pm (ProcessManager)

    the instance of process manager.

  • name (String)

    the loop name.

  • the (Hash<String, Object>)

    loop configuration options from the config file.



51
52
53
54
55
# File 'lib/loops/base.rb', line 51

def initialize(pm, name, config)
  @pm     = pm
  @name   = name
  @config = config
end

Instance Attribute Details

#configHash<String, Object> (readonly)

Returns The hash of loop options from config.

Returns:

  • (Hash<String, Object>)

    The hash of loop options from config.



40
41
42
# File 'lib/loops/base.rb', line 40

def config
  @config
end

#nameString (readonly)

Returns loop name.

Returns:

  • (String)

    loop name.



36
37
38
# File 'lib/loops/base.rb', line 36

def name
  @name
end

Class Method Details

.check_dependenciesObject

Verifies loop dependencies.

Override this method if your loop depends on any external libraries, resources, etc. Verify your dependencies here, and raise an exception in case of any trouble to disallow this loop to start.

Examples:

def self.check_dependencies
  gem 'tinder', '=1.3.1'
end


97
98
# File 'lib/loops/base.rb', line 97

def self.check_dependencies
end

Instance Method Details

#loggerLogger

Get the logger instance.

Returns:

  • (Logger)

    the logger instance.



62
63
64
# File 'lib/loops/base.rb', line 62

def logger
  @pm.logger
end

#runObject

A loop entry point. Should be overridden in descendants.



102
103
104
# File 'lib/loops/base.rb', line 102

def run
  raise 'Generic loop has nothing to do'
end

#shutdown?Boolean

Get a value indicating whether shutdown is in the progress.

Check this flag periodically and if loop is in the shutdown, close all open handlers, update your data, and exit loop as soon as possible to not to loose any sensitive data.

Examples:

if shutdown?
  info('Shutting down!')
  exit(0)
end

Returns:

  • (Boolean)

    a value indicating whether shutdown is in the progress.



81
82
83
# File 'lib/loops/base.rb', line 81

def shutdown?
  @pm.shutdown?
end

#with_lock(entity_ids, loop_id, timeout, entity_name = '', &block) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/loops/base.rb', line 115

def with_lock(entity_ids, loop_id, timeout, entity_name = '', &block)
  entity_name = 'item' if entity_name.to_s.empty?
  entity_ids = [entity_ids] unless Array === entity_ids

  entity_ids.each do |entity_id|
    debug("Locking #{entity_name} #{entity_id}")
    lock = LoopLock.lock(:entity_id => entity_id, :loop => loop_id.to_s, :timeout => timeout)
    unless lock
      warn("Race condition detected for the #{entity_name}: #{entity_id}. Skipping the item.")
      next
    end

    begin
      result = if block.arity == 1
        yield entity_id
      else
        yield
      end
      return result
    ensure
      debug("Unlocking #{entity_name} #{entity_id}")
      LoopLock.unlock(:entity_id => entity_id, :loop => loop_id.to_s)
    end
  end
end

#with_period_of(seconds) ⇒ Object

Raises:

  • (ArgumentError)


141
142
143
144
145
146
147
# File 'lib/loops/base.rb', line 141

def with_period_of(seconds)
  raise ArgumentError, "No block given!" unless block_given?
  loop do
    yield
    sleep(seconds.to_i)
  end
end