Class: Zoidberg::Pool

Inherits:
Object
  • Object
show all
Includes:
Shell
Defined in:
lib/zoidberg/pool.rb

Overview

Populate a collection of instances and proxy requests to free instances within the pool

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Shell

included

Constructor Details

#initialize(*args, &block) ⇒ self

Create a new pool instance. Provide class + instance initialization arguments when creating the pool. These will be used to build all instances within the pool.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/zoidberg/pool.rb', line 20

def initialize(*args, &block)
  _validate_worker_class!(args.first)
  @_signal = Signal.new
  @_worker_count = 1
  @_workers = []
  @builder = lambda do
    inst = args.first.new(
      *args.slice(1, args.size),
      &block
    )
    inst._zoidberg_signal = _signal
    inst
  end
  _zoidberg_balance
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(*args, &block) ⇒ Object

Used to proxy request to worker



79
80
81
82
# File 'lib/zoidberg/pool.rb', line 79

def method_missing(*args, &block)
  worker = _zoidberg_free_worker
  defer{ worker.send(*args, &block) }
end

Instance Attribute Details

#_signalSignal (readonly)



13
14
15
# File 'lib/zoidberg/pool.rb', line 13

def _signal
  @_signal
end

#_workersArray<Object> (readonly)



11
12
13
# File 'lib/zoidberg/pool.rb', line 11

def _workers
  @_workers
end

Instance Method Details

#_validate_worker_class!(klass) ⇒ Object

Validate worker class is properly supervised

Raises:

  • (TypeError)


39
40
41
42
43
# File 'lib/zoidberg/pool.rb', line 39

def _validate_worker_class!(klass)
  unless(klass.ancestors.include?(Zoidberg::Supervise))
    raise TypeError.new "Worker class `#{klass}` must include the `Zoidberg::Supervise` module!"
  end
end

#_worker_count(num = nil) ⇒ Integer

Set or get the number of workers within the pool



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

def _worker_count(num=nil)
  if(num)
    @_worker_count = num.to_i
    _zoidberg_balance
  end
  @_worker_count
end

#_zoidberg_balanceTrueClass

Balance the pool to ensure the correct number of workers are available



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/zoidberg/pool.rb', line 61

def _zoidberg_balance
  unless(_workers.size == _worker_count)
    if(_workers.size < _worker_count)
      (_worker_count - _workers.size).times do
        _workers << @builder.call
      end
    else
      (_workers.size - _worker_count).times do
        worker = _zoidberg_free_worker
        worker._zoidberg_destroy!
        _workers.delete(worker)
      end
    end
  end
  true
end

#_zoidberg_free_workerObject

Find or wait for a free worker



87
88
89
90
91
92
# File 'lib/zoidberg/pool.rb', line 87

def _zoidberg_free_worker
  until(worker = @_workers.detect(&:_zoidberg_available?))
    defer{ _signal.wait_for(:unlocked) }
  end
  worker
end

#terminateObject

Force termination of all workers when terminated



95
96
97
# File 'lib/zoidberg/pool.rb', line 95

def terminate
  @_workers.map(&:_zoidberg_destroy!)
end