Class: Wurk::Flow::Node
- Inherits:
-
Object
- Object
- Wurk::Flow::Node
- Defined in:
- lib/wurk/flow/node.rb
Overview
One node of a flow graph: a single job, plus the edges into and out of it.
Deliberately not a payload. klass, args and options are held exactly
as the caller wrote them and normalized once, at creation, by
Client — a node that pre-built its own job hash would be a second
definition of what a job hash is, and the two would drift.
Built in two phases, because a name may be a forward reference (decision 5
in the slice plan): Builder#job constructs the node with the raw
depends_on refs it was given, and #link! replaces them with resolved
nodes once the whole block has run. Nothing outside the builder sees a
node between the two — Wurk::Flow only ever receives frozen, linked ones.
Instance Attribute Summary collapse
-
#args ⇒ Array
readonly
Positional
perform_asyncarguments, as written. -
#declared ⇒ Array
readonly
The raw
depends_on:refs — nodes, names, or both. -
#dependencies ⇒ Array<Node>
readonly
Resolved dependencies.
-
#dependents ⇒ Array<Node>
readonly
The nodes that depend on this one.
-
#index ⇒ Integer
readonly
Declaration order, 0-based.
-
#klass ⇒ Class, String
readonly
The job class, as written.
-
#level ⇒ Integer
readonly
Longest path from any root, 0-based.
-
#name ⇒ Symbol?
readonly
The name
depends_on:can address this node by. -
#options ⇒ Hash
readonly
Job options merged into the payload at creation (
queue:,retry:,track:, …). -
#pipe ⇒ Node, ...
readonly
The raw
pipe:ref: the one dependency whose stored result is handed to this node as its last argument.
Instance Method Summary collapse
- #feeds_pipe! ⇒ Object
-
#feeds_pipe? ⇒ Boolean
True when some dependent pipes this node's result, so creation has to enqueue it with
track: true— a node whose result nothing reads is not tracked, and tracking is opt-in per job. -
#initialize(index:, klass:, args:, options:, declared:, name: nil, pipe: nil) ⇒ Node
constructor
A new instance of Node.
-
#label ⇒ Object
(also: #to_s)
Every error message in the builder ends up here, so it has to identify a node in a thousand-node graph unambiguously: the class says what it is, the name or index says which one.
- #level!(value) ⇒ Object
-
#link!(nodes) ⇒ Object
Phase two of construction: adopt the resolved dependencies and register this node as their dependent, so the graph is walkable in both directions.
-
#piped? ⇒ Boolean
True when this node is handed its dependency's stored result as its last argument.
- #root? ⇒ Boolean
-
#seal! ⇒ Object
Shallow on purpose.
-
#source ⇒ Node?
The dependency a piped node's argument comes from.
Constructor Details
#initialize(index:, klass:, args:, options:, declared:, name: nil, pipe: nil) ⇒ Node
Returns a new instance of Node.
55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/wurk/flow/node.rb', line 55 def initialize(index:, klass:, args:, options:, declared:, name: nil, pipe: nil) @index = index @name = name @klass = klass @args = args.freeze @options = .freeze @declared = declared.freeze @pipe = pipe @feeds_pipe = false @dependencies = [] @dependents = [] @level = 0 end |
Instance Attribute Details
#args ⇒ Array (readonly)
Returns positional perform_async arguments, as written.
29 30 31 |
# File 'lib/wurk/flow/node.rb', line 29 def args @args end |
#declared ⇒ Array (readonly)
Returns the raw depends_on: refs — nodes, names, or both.
37 38 39 |
# File 'lib/wurk/flow/node.rb', line 37 def declared @declared end |
#dependencies ⇒ Array<Node> (readonly)
Returns resolved dependencies. This node runs after all of them succeed.
46 47 48 |
# File 'lib/wurk/flow/node.rb', line 46 def dependencies @dependencies end |
#dependents ⇒ Array<Node> (readonly)
Returns the nodes that depend on this one.
49 50 51 |
# File 'lib/wurk/flow/node.rb', line 49 def dependents @dependents end |
#index ⇒ Integer (readonly)
Returns declaration order, 0-based. The node's identity when it has no name: stable, and what creation orders writes by.
20 21 22 |
# File 'lib/wurk/flow/node.rb', line 20 def index @index end |
#klass ⇒ Class, String (readonly)
Returns the job class, as written.
26 27 28 |
# File 'lib/wurk/flow/node.rb', line 26 def klass @klass end |
#level ⇒ Integer (readonly)
Returns longest path from any root, 0-based. Assigned in topological order, so a node's level is final by the time it is read.
53 54 55 |
# File 'lib/wurk/flow/node.rb', line 53 def level @level end |
#name ⇒ Symbol? (readonly)
Returns the name depends_on: can address this node by.
23 24 25 |
# File 'lib/wurk/flow/node.rb', line 23 def name @name end |
#options ⇒ Hash (readonly)
Returns job options merged into the payload at creation
(queue:, retry:, track:, …). Not validated here: Client
owns what a valid option is, and duplicating that check would fork it.
34 35 36 |
# File 'lib/wurk/flow/node.rb', line 34 def @options end |
#pipe ⇒ Node, ... (readonly)
Returns the raw pipe: ref: the one
dependency whose stored result is handed to this node as its last
argument. nil for every ordinary node.
42 43 44 |
# File 'lib/wurk/flow/node.rb', line 42 def pipe @pipe end |
Instance Method Details
#feeds_pipe! ⇒ Object
87 88 89 90 |
# File 'lib/wurk/flow/node.rb', line 87 def feeds_pipe! @feeds_pipe = true self end |
#feeds_pipe? ⇒ Boolean
Returns true when some dependent pipes this node's result, so
creation has to enqueue it with track: true — a node whose result
nothing reads is not tracked, and tracking is opt-in per job.
84 |
# File 'lib/wurk/flow/node.rb', line 84 def feeds_pipe? = @feeds_pipe |
#label ⇒ Object Also known as: to_s
Every error message in the builder ends up here, so it has to identify a node in a thousand-node graph unambiguously: the class says what it is, the name or index says which one.
95 |
# File 'lib/wurk/flow/node.rb', line 95 def label = "#{@klass}[#{@name ? @name.inspect : "##{@index}"}]" |
#level!(value) ⇒ Object
108 109 110 111 |
# File 'lib/wurk/flow/node.rb', line 108 def level!(value) @level = value self end |
#link!(nodes) ⇒ Object
Phase two of construction: adopt the resolved dependencies and register this node as their dependent, so the graph is walkable in both directions. Builder-only — a node linked twice would double its edges.
102 103 104 105 106 |
# File 'lib/wurk/flow/node.rb', line 102 def link!(nodes) @dependencies.concat(nodes) nodes.each { |node| node.dependents << self } self end |
#piped? ⇒ Boolean
Returns true when this node is handed its dependency's stored result as its last argument.
73 |
# File 'lib/wurk/flow/node.rb', line 73 def piped? = !@pipe.nil? |
#root? ⇒ Boolean
69 |
# File 'lib/wurk/flow/node.rb', line 69 def root? = @dependencies.empty? |
#seal! ⇒ Object
Shallow on purpose. The edge arrays and the node are sealed because the
graph is validated and must not change afterwards; args and options
are frozen at construction but their contents are the caller's, and
deep-freezing someone's argument objects is a side effect on their data.
117 118 119 120 121 |
# File 'lib/wurk/flow/node.rb', line 117 def seal! @dependencies.freeze @dependents.freeze freeze end |
#source ⇒ Node?
Returns the dependency a piped node's argument comes from.
The only dependency: Builder refuses pipe: on a node with
more than one, because the graph is what makes "the upstream result"
a single well-defined value (decision 2 in the slice plan).
79 |
# File 'lib/wurk/flow/node.rb', line 79 def source = @dependencies.first |