rachinations 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/rachinations.rb +2 -0
- data/lib/rachinations/domain/diagrams/diagram.rb +13 -11
- data/lib/rachinations/domain/diagrams/verbose_diagram.rb +1 -1
- data/lib/rachinations/domain/edges/edge.rb +21 -13
- data/lib/rachinations/domain/modules/common/schedulable_tasks.rb +27 -0
- data/lib/rachinations/dsl/bootstrap.rb +82 -11
- data/lib/rachinations/dsl/diagram_shorthand_methods.rb +0 -1
- data/lib/rachinations/version.rb +1 -1
- data/testing/spec/release1/dsl_spec.rb +45 -13
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f121ae6b88636bb8f2d61ce349052e5eaaab765a
|
4
|
+
data.tar.gz: 80b8154cb68f75059ed98c866043b052c1271ac0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 555791bf758a0458b7cfc3b1c71287c33b54ce296d957878f4c4d236fb0186a8b1aaf036529119b5a85bd40eeeeacf152e7bf2df87590040f75a89330c52e067
|
7
|
+
data.tar.gz: 1443bdad6609c32eb441b22e686c46b04c531808f190301ed0de56d309730ff2b94cd7b47dc4244e252594188fe9b2939caad027c72168a3f9512cd0a9a2fd9b
|
data/Gemfile.lock
CHANGED
data/lib/rachinations.rb
CHANGED
@@ -4,6 +4,8 @@ require 'rachinations/version'
|
|
4
4
|
|
5
5
|
require 'rachinations/domain/modules/common/refiners/proc_convenience_methods'
|
6
6
|
require 'rachinations/domain/modules/common/refiners/number_modifiers'
|
7
|
+
require 'rachinations/domain/modules/common/schedulable_tasks'
|
8
|
+
|
7
9
|
|
8
10
|
require 'rachinations/extras/fifo'
|
9
11
|
|
@@ -1,10 +1,12 @@
|
|
1
1
|
require_relative '../../domain/modules/common/invariant'
|
2
|
+
require_relative '../../domain/modules/common/schedulable_tasks'
|
2
3
|
require_relative '../edge_collection'
|
3
4
|
require_relative '../node_collection'
|
4
5
|
|
5
6
|
class Diagram
|
6
7
|
|
7
8
|
include Invariant
|
9
|
+
include SchedulableTasks
|
8
10
|
|
9
11
|
attr_accessor :name, :max_iterations, :nodes, :edges
|
10
12
|
|
@@ -56,14 +58,15 @@ class Diagram
|
|
56
58
|
node.attach_condition &condition
|
57
59
|
|
58
60
|
if !triggered_by.nil?
|
61
|
+
|
59
62
|
# ask the current class (diagram) to evaluate what node it is
|
60
|
-
triggerer =
|
63
|
+
triggerer = get_node(triggered_by)
|
61
64
|
triggerer.attach_trigger(node)
|
62
65
|
end
|
63
66
|
|
64
67
|
if !triggers.nil?
|
65
|
-
# ask the
|
66
|
-
triggeree =
|
68
|
+
# ask the diagram to evaluate what node it is
|
69
|
+
triggeree = get_node(triggers)
|
67
70
|
node.attach_trigger(triggeree)
|
68
71
|
end
|
69
72
|
|
@@ -77,17 +80,16 @@ class Diagram
|
|
77
80
|
|
78
81
|
params.store(:diagram, self)
|
79
82
|
|
80
|
-
#
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
params.store(:
|
85
|
-
params.store(:to, to)
|
83
|
+
# replace node names in params with the actual nodes
|
84
|
+
node_from = get_node(params.delete(:from))
|
85
|
+
params.store(:from, node_from)
|
86
|
+
node_to = get_node(params.delete(:to))
|
87
|
+
params.store(:to, node_to)
|
86
88
|
|
87
89
|
edge = edge_klass.new(params)
|
88
90
|
|
89
|
-
|
90
|
-
|
91
|
+
node_from.attach_edge!(edge)
|
92
|
+
node_to.attach_edge!(edge)
|
91
93
|
|
92
94
|
edges.push(edge)
|
93
95
|
|
@@ -5,11 +5,12 @@ require_relative '../../../../lib/rachinations/domain/modules/common/refiners/nu
|
|
5
5
|
|
6
6
|
class Edge
|
7
7
|
include HashInit
|
8
|
-
using NumberModifiers
|
9
8
|
|
9
|
+
using NumberModifiers
|
10
10
|
|
11
11
|
attr_reader :from, :to, :name, :types
|
12
12
|
|
13
|
+
attr_writer :from, :to
|
13
14
|
|
14
15
|
def label
|
15
16
|
if @label.is_a?(Proc)
|
@@ -27,14 +28,14 @@ class Edge
|
|
27
28
|
|
28
29
|
@name = params.fetch(:name, 'anonymous')
|
29
30
|
|
30
|
-
@from = params.fetch(:from)
|
31
|
-
|
32
|
-
@to = params.fetch(:to)
|
33
|
-
|
34
31
|
@label = params.fetch(:label)
|
35
32
|
|
36
33
|
@types = params.fetch(:types)
|
37
34
|
|
35
|
+
@from = params.fetch(:from) if params.has_key?(:from)
|
36
|
+
|
37
|
+
@to = params.fetch(:to) if params.has_key?(:to)
|
38
|
+
|
38
39
|
end
|
39
40
|
|
40
41
|
# Simulates a ping!, but no resources get actually
|
@@ -46,7 +47,7 @@ class Edge
|
|
46
47
|
#
|
47
48
|
# @return [Boolean] true in case a ping! on this Edge
|
48
49
|
# would return true. False otherwise.
|
49
|
-
def test_ping?(require_all:false)
|
50
|
+
def test_ping?(require_all: false)
|
50
51
|
return false if from.disabled? || to.disabled?
|
51
52
|
|
52
53
|
condition = strategy.condition
|
@@ -123,10 +124,13 @@ class Edge
|
|
123
124
|
# end of this Edge.
|
124
125
|
#
|
125
126
|
# @raise [RuntimeError] in case the receiving node or this Edge
|
126
|
-
#
|
127
|
+
# won't accept the resource sent.
|
128
|
+
# @raise [RuntimeError] if this edge hasn't defined :from and :to
|
129
|
+
# instance variables
|
127
130
|
# @param res [Token] the resource to send.
|
128
131
|
def push!(res)
|
129
|
-
raise RuntimeError, "
|
132
|
+
raise RuntimeError, "Edge does not support type: #{res.type}" unless supports?(res.type)
|
133
|
+
raise RuntimeError, "Please define instance variables :from and :to" unless instance_variable_defined?(:@from) && instance_variable_defined?(:@to)
|
130
134
|
|
131
135
|
begin
|
132
136
|
to.put_resource!(res, self)
|
@@ -136,16 +140,20 @@ class Edge
|
|
136
140
|
end
|
137
141
|
|
138
142
|
# Tries to take a resource matching given block
|
139
|
-
#
|
143
|
+
# from the node at the other end.
|
140
144
|
#
|
141
145
|
# @param [Proc] blk block that will define what resource the other node
|
142
|
-
#
|
146
|
+
# should send.
|
143
147
|
# @raise [RuntimeError] in case the other node could provide no resources
|
144
|
-
#
|
148
|
+
# that satisfy this condition block.
|
149
|
+
# @raise [RuntimeError] if this edge hasn't defined :from and :to
|
150
|
+
# instance variables
|
145
151
|
# @return [Token,nil] a Resource that satisfies the given block or nil,
|
146
|
-
#
|
152
|
+
# if the pull was not performed for some reason (e.g. it's probabilistic)
|
147
153
|
def pull!(blk)
|
148
154
|
|
155
|
+
raise RuntimeError, "Please define instance variables :from and :to" unless instance_variable_defined?(:@from) && instance_variable_defined?(:@to)
|
156
|
+
|
149
157
|
begin
|
150
158
|
res=from.take_resource!(blk)
|
151
159
|
rescue => e
|
@@ -175,7 +183,7 @@ class Edge
|
|
175
183
|
end
|
176
184
|
|
177
185
|
def options
|
178
|
-
[:name
|
186
|
+
[:name, :label, :types, :diagram, :from, :to]
|
179
187
|
end
|
180
188
|
|
181
189
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
module SchedulableTasks
|
3
|
+
def schedule_task(method, *params)
|
4
|
+
task = Hash.new
|
5
|
+
task[:method] = method
|
6
|
+
task[:params] = params
|
7
|
+
|
8
|
+
@scheduled_tasks ||= Array.new
|
9
|
+
@scheduled_tasks << task
|
10
|
+
end
|
11
|
+
|
12
|
+
def scheduled_tasks
|
13
|
+
@scheduled_tasks ||= Array.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def run_scheduled_tasks
|
17
|
+
scheduled_tasks.each do |task|
|
18
|
+
|
19
|
+
method = task[:method]
|
20
|
+
params = task[:params]
|
21
|
+
|
22
|
+
|
23
|
+
method.call(*params)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -18,24 +18,95 @@ module DSL
|
|
18
18
|
raise BadDSL, "Unknown diagram mode: #{mode.to_s}"
|
19
19
|
end
|
20
20
|
|
21
|
-
#
|
22
|
-
#
|
23
|
-
|
21
|
+
# This is a modified version of Diagram#add_edge!. It defers some method
|
22
|
+
# calls that involve other nodes until after the end of the block that
|
23
|
+
# builds the diagram. this is done because, when these options are set,
|
24
|
+
# the nodes may not have been created yet.
|
25
|
+
# @param [Class] the edge class. probably Edge
|
26
|
+
# @param [Hash] params params to be passed to the constructor of given class
|
27
|
+
def dia.add_edge!(edge_klass, params)
|
24
28
|
|
25
|
-
|
29
|
+
params.store(:diagram, self)
|
26
30
|
|
27
|
-
|
31
|
+
from_node_name = params.fetch(:from)
|
32
|
+
to_node_name = params.fetch(:to)
|
28
33
|
|
29
|
-
|
34
|
+
edge = edge_klass.new(params)
|
30
35
|
|
31
|
-
|
36
|
+
# this method may contain nodes that may not yet exist
|
37
|
+
edge_attach_from = lambda do |edge, node_name, diagram|
|
38
|
+
# ask the diagram to evaluate what node it is
|
39
|
+
node = diagram.get_node(node_name)
|
40
|
+
node.attach_edge!(edge)
|
41
|
+
edge.from = node
|
42
|
+
end
|
43
|
+
|
44
|
+
# this method may contain nodes that may not yet exist
|
45
|
+
edge_attach_to = lambda do |edge, node_name, diagram|
|
46
|
+
# ask the diagram to evaluate what node it is
|
47
|
+
node = diagram.get_node(node_name)
|
48
|
+
node.attach_edge!(edge)
|
49
|
+
edge.to = node
|
50
|
+
end
|
51
|
+
|
52
|
+
# so they need to be scheduled and run later
|
53
|
+
schedule_task(edge_attach_from, edge, from_node_name, self)
|
54
|
+
schedule_task(edge_attach_to, edge, to_node_name, self)
|
55
|
+
|
56
|
+
edges.push(edge)
|
57
|
+
|
58
|
+
self
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
def dia.add_node!(node_klass, params)
|
63
|
+
|
64
|
+
params.store(:diagram, self)
|
65
|
+
|
66
|
+
# if there's a condition, return it, otherwise return default condition
|
67
|
+
condition = params.delete(:condition) { lambda { true } }
|
68
|
+
|
69
|
+
# similarly, if nodes are supposed to be triggered by another node
|
70
|
+
triggered_by = params.delete(:triggered_by) { nil }
|
71
|
+
|
72
|
+
# akin to :triggered_by, but it's defined in the triggerER
|
73
|
+
# rather than in the trigerrEE
|
74
|
+
triggers = params.delete(:triggers) { nil }
|
75
|
+
|
76
|
+
node = node_klass.new(params)
|
77
|
+
|
78
|
+
node.attach_condition &condition
|
79
|
+
|
80
|
+
if !triggered_by.nil?
|
81
|
+
|
82
|
+
attach_trigger_task = lambda do |triggeree, triggerer_name, diagram|
|
83
|
+
# ask the diagram to evaluate what node it is
|
84
|
+
triggerer = diagram.get_node(triggerer_name)
|
85
|
+
triggerer.attach_trigger(triggeree)
|
86
|
+
end
|
87
|
+
schedule_task(attach_trigger_task, node, triggered_by, self)
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
if !triggers.nil?
|
92
|
+
|
93
|
+
attach_trigger_task = lambda do |triggerer, triggeree_name, diagram|
|
94
|
+
# ask the diagram to evaluate what node it is
|
95
|
+
triggeree = diagram.send(triggeree_name.to_sym)
|
96
|
+
triggerer.attach_trigger(triggeree)
|
97
|
+
end
|
98
|
+
schedule_task(attach_trigger_task, node, triggers, self)
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
nodes.push(node)
|
103
|
+
|
104
|
+
self
|
32
105
|
|
33
|
-
# cant verbose be a simple boolean instead?
|
34
|
-
if verbose === :verbose
|
35
|
-
dia.extend(Verbose)
|
36
106
|
end
|
37
107
|
|
38
|
-
dia.instance_eval
|
108
|
+
dia.instance_eval(&blk)
|
109
|
+
dia.run_scheduled_tasks
|
39
110
|
|
40
111
|
dia
|
41
112
|
|
data/lib/rachinations/version.rb
CHANGED
@@ -219,20 +219,52 @@ describe Diagram do
|
|
219
219
|
end
|
220
220
|
|
221
221
|
|
222
|
-
|
223
|
-
#
|
224
|
-
# expect do
|
225
|
-
#
|
226
|
-
# d = diagram do
|
227
|
-
# pool 'p2', initial_value: 7 # this will be triggered 10 times
|
228
|
-
# edge from: 'p2', to: 'p3'
|
229
|
-
# pool 'p3'
|
230
|
-
# end
|
231
|
-
#
|
232
|
-
# end.not_to raise_error
|
233
|
-
#
|
234
|
-
# end
|
222
|
+
it "accepts declaring forward-referencing of non existing nodes" do
|
235
223
|
|
224
|
+
expect do
|
225
|
+
# triggered_by forward referencing a node
|
226
|
+
diagram do
|
227
|
+
pool 'p2', 7, triggered_by: 'p3'
|
228
|
+
pool 'p3'
|
229
|
+
end
|
230
|
+
end.not_to raise_error
|
231
|
+
|
232
|
+
expect do
|
233
|
+
# edge forward referencing its connected nodes
|
234
|
+
d = diagram do
|
235
|
+
pool 'p2', initial_value: 7 # this will be triggered 10 times
|
236
|
+
edge from: 'p2', to: 'p3'
|
237
|
+
pool 'p3'
|
238
|
+
end
|
239
|
+
|
240
|
+
end.not_to raise_error
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'runs diagrams using forward-referencing' do
|
245
|
+
|
246
|
+
d = diagram do
|
247
|
+
pool 'p2',:automatic, :push_any, initial_value: 7 # this will be triggered 10 times
|
248
|
+
edge from: 'p2', to: 'p3'
|
249
|
+
pool 'p3'
|
250
|
+
end
|
251
|
+
|
252
|
+
d.run 10
|
253
|
+
|
254
|
+
expect(d.p3.resource_count).to eq 7
|
255
|
+
|
256
|
+
d2 = diagram do
|
257
|
+
pool :automatic, triggers: 'p2'
|
258
|
+
pool 'p2', :push_any, initial_value: 10
|
259
|
+
pool 'p3'
|
260
|
+
edge from: 'p2', to: 'p3'
|
261
|
+
end
|
262
|
+
|
263
|
+
d2.run 10
|
264
|
+
expect(d2.p3.resource_count).to eq 10
|
265
|
+
expect(d2.p2.resource_count).to eq 0
|
266
|
+
|
267
|
+
end
|
236
268
|
|
237
269
|
end
|
238
270
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rachinations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felipe Almeida
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -170,6 +170,7 @@ files:
|
|
170
170
|
- lib/rachinations/domain/modules/common/invariant.rb
|
171
171
|
- lib/rachinations/domain/modules/common/refiners/number_modifiers.rb
|
172
172
|
- lib/rachinations/domain/modules/common/refiners/proc_convenience_methods.rb
|
173
|
+
- lib/rachinations/domain/modules/common/schedulable_tasks.rb
|
173
174
|
- lib/rachinations/domain/modules/diagrams/verbose.rb
|
174
175
|
- lib/rachinations/domain/node_collection.rb
|
175
176
|
- lib/rachinations/domain/nodes/converter.rb
|