Class: Shifty::Worker

Inherits:
Object
  • Object
show all
Includes:
PolicyDeclarable, Taggable
Defined in:
lib/shifty/worker.rb

Overview

Shifty::Worker uses Ruby Fibers for cooperative multitasking. This results in a single-threaded execution model where workers explicitly yield control to one another. This model is chosen for its simplicity and suitability for creating chainable data processing pipelines, where each worker performs a specific task and passes its output to the next worker in the chain.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from PolicyDeclarable

#freeze!, #with_policy

Methods included from Taggable

#criteria=, #criteria_passes?, #has_tag?, #tags=

Constructor Details

#initialize(p = {}, &block) ⇒ Worker

Returns a new instance of Worker.



18
19
20
21
22
23
24
25
26
# File 'lib/shifty/worker.rb', line 18

def initialize(p = {}, &block)
  @supply       = p[:supply]
  @task         = block || p[:task]
  @context      = p[:context] || OpenStruct.new
  @policy       = Policy.validate!(p[:policy]) if p[:policy]
  @name         = p[:name]
  self.criteria = p[:criteria]
  self.tags     = p[:tags]
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



12
13
14
# File 'lib/shifty/worker.rb', line 12

def name
  @name
end

#pipeline_policyObject

Returns the value of attribute pipeline_policy.



13
14
15
# File 'lib/shifty/worker.rb', line 13

def pipeline_policy
  @pipeline_policy
end

#supplyObject

Returns the value of attribute supply.



12
13
14
# File 'lib/shifty/worker.rb', line 12

def supply
  @supply
end

#tagsObject (readonly)

Returns the value of attribute tags.



12
13
14
# File 'lib/shifty/worker.rb', line 12

def tags
  @tags
end

Instance Method Details

#effective_policyObject



28
29
30
# File 'lib/shifty/worker.rb', line 28

def effective_policy
  @policy || pipeline_policy || Shifty.config.default_policy
end

#freeze_topology_node!Object

Materializes lazy state (default task, the Fiber) so that freezing this instance cannot surprise it later with a FrozenError on ivar assignment mid-shift, then freezes it.



55
56
57
58
59
# File 'lib/shifty/worker.rb', line 55

def freeze_topology_node!
  ensure_ready_to_work!
  workflow
  freeze
end

#intake(value) ⇒ Object

Applies this worker's effective policy to a value crossing its boundary. Public because Policy::Supply routes a task's own supply.shift calls back through it.



35
36
37
# File 'lib/shifty/worker.rb', line 35

def intake(value)
  Policy.resolve(effective_policy).call(value, worker: self)
end

#ready_to_work?Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/shifty/worker.rb', line 61

def ready_to_work?
  @task && (supply || !task_accepts_a_value?)
end

#shiftObject



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/shifty/worker.rb', line 39

def shift
  ensure_ready_to_work!
  workflow.resume
rescue PolicyError
  # The raising Fiber is terminated and can never be resumed; discard
  # it so a caller that rescues the violation can keep shifting.
  # Closure and context state survive — only the loop restarts.
  # (A #freeze!-d worker can't rebuild its Fiber, so a violation
  # there ends the pipeline — the topology guarantee wins.)
  @my_little_machine = nil unless frozen?
  raise
end

#suppliable?Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/shifty/worker.rb', line 76

def suppliable?
  @task && @task.arity > 0
end

#supplies(subscribing_worker) ⇒ Object Also known as: |



65
66
67
68
# File 'lib/shifty/worker.rb', line 65

def supplies(subscribing_worker)
  subscribing_worker.supply = self
  subscribing_worker
end