phronomy 0.17.0 → 0.19.0
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/CHANGELOG.md +122 -1134
- data/README.md +70 -1280
- data/benchmark/bench_regression.rb +25 -5
- data/docs/changelog/0.14-and-earlier.md +1137 -0
- data/docs/decisions/008-orchestrator-uses-os-threads.md +46 -48
- data/docs/decisions/009-state-store-abstraction.md +1 -1
- data/docs/decisions/010-cooperative-first-concurrency.md +155 -235
- data/docs/decisions/014-unified-persistence-durable-state.md +268 -0
- data/docs/features.md +93 -0
- data/docs/getting-started.md +387 -0
- data/docs/migrations/0.15.md +35 -0
- data/docs/migrations/0.16.md +43 -0
- data/docs/migrations/0.19.md +148 -0
- data/docs/runtime-and-concurrency.md +349 -0
- data/examples/workflows/generic_task_event_mapping.rb +14 -6
- data/lib/phronomy/agent/agent_invocation_session_builder.rb +2 -2
- data/lib/phronomy/agent/async_event_api.rb +3 -3
- data/lib/phronomy/agent/base.rb +116 -55
- data/lib/phronomy/agent/context/capability/base.rb +13 -3
- data/lib/phronomy/agent/context_assembler.rb +13 -3
- data/lib/phronomy/agent/execution_coordinator.rb +423 -252
- data/lib/phronomy/agent/journal_projection.rb +5 -1
- data/lib/phronomy/agent/shared_state.rb +2 -0
- data/lib/phronomy/agent/tool_executor.rb +29 -71
- data/lib/phronomy/agent/tool_invocation.rb +97 -47
- data/lib/phronomy/agent/tool_invocation_session_builder.rb +55 -161
- data/lib/phronomy/configuration.rb +7 -30
- data/lib/phronomy/diagnostics.rb +12 -41
- data/lib/phronomy/engine/concurrency/async_queue.rb +5 -188
- data/lib/phronomy/engine/concurrency/cancellation_scope.rb +6 -7
- data/lib/phronomy/engine/concurrency/cancellation_token.rb +48 -3
- data/lib/phronomy/engine/concurrency/deadline.rb +2 -3
- data/lib/phronomy/engine/concurrency/offload_pool.rb +696 -0
- data/lib/phronomy/engine/concurrency/pool_registry.rb +5 -5
- data/lib/phronomy/engine/event_loop.rb +170 -193
- data/lib/phronomy/engine/fsm_session.rb +6 -4
- data/lib/phronomy/engine/runtime/timer_queue.rb +48 -71
- data/lib/phronomy/engine/runtime/timer_service.rb +13 -21
- data/lib/phronomy/engine/runtime.rb +52 -158
- data/lib/phronomy/engine/task.rb +136 -277
- data/lib/phronomy/llm_adapter/base.rb +14 -14
- data/lib/phronomy/llm_adapter/ruby_llm.rb +3 -4
- data/lib/phronomy/llm_adapter.rb +2 -2
- data/lib/phronomy/metrics.rb +15 -30
- data/lib/phronomy/multi_agent/fan_out_invocation.rb +146 -0
- data/lib/phronomy/multi_agent/fan_out_session_builder.rb +125 -0
- data/lib/phronomy/multi_agent/handoff.rb +1 -0
- data/lib/phronomy/multi_agent/orchestrator.rb +147 -99
- data/lib/phronomy/multi_agent/team_coordinator.rb +2 -0
- data/lib/phronomy/persistence/in_memory.rb +113 -8
- data/lib/phronomy/persistence.rb +12 -3
- data/lib/phronomy/testing/eval/comparison.rb +23 -0
- data/lib/phronomy/testing/eval/dataset.rb +27 -0
- data/lib/phronomy/testing/eval/eval_case.rb +13 -0
- data/lib/phronomy/testing/eval/eval_result.rb +16 -0
- data/lib/phronomy/testing/eval/metrics.rb +43 -0
- data/lib/phronomy/testing/eval/runner.rb +52 -0
- data/lib/phronomy/testing/eval/scorer/base.rb +15 -0
- data/lib/phronomy/testing/eval/scorer/exact_match.rb +25 -0
- data/lib/phronomy/testing/eval/scorer/includes_scorer.rb +25 -0
- data/lib/phronomy/testing/eval/scorer/llm_judge.rb +46 -0
- data/lib/phronomy/testing/eval/scorer.rb +10 -0
- data/lib/phronomy/testing/eval.rb +9 -0
- data/lib/phronomy/testing/fake_clock.rb +6 -53
- data/lib/phronomy/testing.rb +2 -6
- data/lib/phronomy/tools/agent.rb +141 -6
- data/lib/phronomy/vector_store/async_backend.rb +21 -17
- data/lib/phronomy/vector_store/base.rb +2 -2
- data/lib/phronomy/vector_store/embeddings/base.rb +6 -5
- data/lib/phronomy/version.rb +1 -1
- data/lib/phronomy/workflow.rb +10 -9
- data/lib/phronomy/workflow_runner.rb +363 -99
- data/lib/phronomy.rb +10 -4
- data/scripts/api_snapshot.rb +4 -4
- metadata +25 -33
- data/lib/phronomy/engine/concurrency/blocking_adapter_pool.rb +0 -561
- data/lib/phronomy/engine/runtime/deterministic_scheduler.rb +0 -439
- data/lib/phronomy/engine/runtime/fake_scheduler.rb +0 -165
- data/lib/phronomy/engine/runtime/runtime_metrics.rb +0 -116
- data/lib/phronomy/engine/runtime/scheduler.rb +0 -98
- data/lib/phronomy/engine/runtime/scheduler_timer_adapter.rb +0 -79
- data/lib/phronomy/engine/runtime/task_registry.rb +0 -95
- data/lib/phronomy/engine/runtime/thread_scheduler.rb +0 -30
- data/lib/phronomy/engine/task/backend.rb +0 -80
- data/lib/phronomy/engine/task/deferred_backend.rb +0 -73
- data/lib/phronomy/engine/task/fiber_backend.rb +0 -157
- data/lib/phronomy/engine/task/immediate_backend.rb +0 -89
- data/lib/phronomy/engine/task/mapped_backend.rb +0 -90
- data/lib/phronomy/engine/task/thread_backend.rb +0 -84
- data/lib/phronomy/engine/task_group.rb +0 -193
- data/lib/phronomy/eval/comparison.rb +0 -47
- data/lib/phronomy/eval/dataset.rb +0 -45
- data/lib/phronomy/eval/eval_case.rb +0 -17
- data/lib/phronomy/eval/eval_result.rb +0 -29
- data/lib/phronomy/eval/metrics.rb +0 -66
- data/lib/phronomy/eval/runner.rb +0 -94
- data/lib/phronomy/eval/scorer/base.rb +0 -22
- data/lib/phronomy/eval/scorer/exact_match.rb +0 -31
- data/lib/phronomy/eval/scorer/includes_scorer.rb +0 -32
- data/lib/phronomy/eval/scorer/llm_judge.rb +0 -72
- data/lib/phronomy/eval/scorer.rb +0 -9
- data/lib/phronomy/eval.rb +0 -7
- data/lib/phronomy/state_store/base.rb +0 -48
- data/lib/phronomy/state_store/in_memory.rb +0 -62
- data/lib/phronomy/testing/fake_scheduler.rb +0 -104
- data/lib/phronomy/testing/scheduler_helpers.rb +0 -68
data/lib/phronomy/tools/agent.rb
CHANGED
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
module Phronomy
|
|
4
4
|
module Tools
|
|
5
|
-
# Wraps a Phronomy::Agent::Base subclass as a callable
|
|
6
|
-
#
|
|
5
|
+
# Wraps a Phronomy::Agent::Base subclass as a callable Tool.
|
|
6
|
+
#
|
|
7
|
+
# Agent-backed Tools are logically asynchronous rather than offloaded
|
|
8
|
+
# synchronous operations. Their ToolInvocation starts the child Agent and then
|
|
9
|
+
# returns to EventLoop immediately; the Tool completion handle settles when the
|
|
10
|
+
# child Agent FSMSession finishes. An OffloadPool worker is therefore never
|
|
11
|
+
# consumed merely to wait for another Agent.
|
|
7
12
|
class Agent < Phronomy::Agent::Context::Capability::Base
|
|
8
|
-
|
|
9
|
-
|
|
13
|
+
execution_mode :cooperative
|
|
14
|
+
description "Wraps a Phronomy::Agent as a Tool"
|
|
15
|
+
param :input, type: :string, desc: "The input to forward to the wrapped Agent"
|
|
10
16
|
|
|
11
17
|
class << self
|
|
12
18
|
def from_agent(agent_class, tool_name: nil, description: nil)
|
|
@@ -25,13 +31,38 @@ module Phronomy
|
|
|
25
31
|
|
|
26
32
|
klass.tool_name(effective_name)
|
|
27
33
|
klass.description(effective_desc)
|
|
28
|
-
|
|
34
|
+
|
|
35
|
+
# Preserve the synchronous Tool API for top-level callers. ToolInvocation
|
|
36
|
+
# never uses this path for Agent-backed Tools; it calls #call_async.
|
|
37
|
+
klass.define_method(:execute) do |input:, cancellation_token: nil|
|
|
38
|
+
invoke_options = {}
|
|
39
|
+
if cancellation_token
|
|
40
|
+
invoke_options[:config] = {cancellation_token: cancellation_token}
|
|
41
|
+
end
|
|
29
42
|
result = Phronomy::Agent.run_once(
|
|
30
43
|
definition: agent_class,
|
|
31
|
-
input: input
|
|
44
|
+
input: input,
|
|
45
|
+
**invoke_options
|
|
32
46
|
)
|
|
33
47
|
result[:output].to_s
|
|
34
48
|
end
|
|
49
|
+
|
|
50
|
+
# Internal asynchronous execution protocol used by Agent#call_async.
|
|
51
|
+
# The child Agent owns its own FSMSession/EventLoop lifecycle; this
|
|
52
|
+
# method only returns its completion handle and performs a short map.
|
|
53
|
+
klass.define_method(:execute_async) do |input:, cancellation_token: nil, config: {}|
|
|
54
|
+
persistence = Phronomy::Persistence::InMemory.new
|
|
55
|
+
agent = agent_class.create(persistence: persistence)
|
|
56
|
+
task_config = (config || {}).dup
|
|
57
|
+
if cancellation_token && !task_config[:cancellation_token]
|
|
58
|
+
task_config[:cancellation_token] = cancellation_token
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
agent.invoke_async(input, config: task_config).map do |result|
|
|
62
|
+
result[:output].to_s
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
klass.send(:private, :execute_async)
|
|
35
66
|
klass
|
|
36
67
|
end
|
|
37
68
|
|
|
@@ -49,6 +80,110 @@ module Phronomy
|
|
|
49
80
|
.sub(/_tool$/, "")
|
|
50
81
|
end
|
|
51
82
|
end
|
|
83
|
+
|
|
84
|
+
# Agent-backed Tools have an asynchronous implementation that does not use
|
|
85
|
+
# ToolExecutor/OffloadPool. Validation and Tool error policy still match
|
|
86
|
+
# Capability::Base#call.
|
|
87
|
+
def call_async(
|
|
88
|
+
args,
|
|
89
|
+
cancellation_token: nil,
|
|
90
|
+
config: {}
|
|
91
|
+
)
|
|
92
|
+
cancellation_token&.raise_if_cancelled!
|
|
93
|
+
validated_args, schema_error = send(:validate_and_coerce, args)
|
|
94
|
+
|
|
95
|
+
if schema_error
|
|
96
|
+
return schema_error_task(schema_error)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
source = execute_async(
|
|
100
|
+
**(validated_args || {}),
|
|
101
|
+
cancellation_token: cancellation_token,
|
|
102
|
+
config: config || {}
|
|
103
|
+
)
|
|
104
|
+
unless source.respond_to?(:on_complete)
|
|
105
|
+
raise Phronomy::ToolError,
|
|
106
|
+
"#{self.class.name} asynchronous execution must return a completion handle"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
result_task = Phronomy::Task.deferred(name: "agent-tool-#{name}")
|
|
110
|
+
source.on_complete do |result, error|
|
|
111
|
+
if error
|
|
112
|
+
settle_async_error(result_task, error)
|
|
113
|
+
next
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
begin
|
|
117
|
+
result_task.complete(send(:truncate_result_if_needed, result))
|
|
118
|
+
rescue => result_error
|
|
119
|
+
settle_async_error(result_task, result_error)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
result_task
|
|
123
|
+
rescue Phronomy::ToolError, Phronomy::CancellationError => error
|
|
124
|
+
failed_task(error)
|
|
125
|
+
rescue => error
|
|
126
|
+
result_task = Phronomy::Task.deferred(name: "agent-tool-#{name}")
|
|
127
|
+
settle_async_error(result_task, error)
|
|
128
|
+
result_task
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
# Subclasses created by .from_agent and Orchestrator override this method.
|
|
134
|
+
# It deliberately remains private so it is not part of the public Tool API.
|
|
135
|
+
def execute_async(input:, cancellation_token: nil, config: {})
|
|
136
|
+
task = Phronomy::Task.deferred(name: "agent-tool-#{name}-fallback")
|
|
137
|
+
begin
|
|
138
|
+
task.complete(execute(input: input, cancellation_token: cancellation_token))
|
|
139
|
+
rescue => error
|
|
140
|
+
task.fail(error)
|
|
141
|
+
end
|
|
142
|
+
task
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def schema_error_task(schema_error)
|
|
146
|
+
task = Phronomy::Task.deferred(name: "agent-tool-#{name}-schema")
|
|
147
|
+
if self.class.on_schema_error == :raise
|
|
148
|
+
task.fail(Phronomy::ToolError.new(
|
|
149
|
+
"#{self.class.name} schema error: #{schema_error}"
|
|
150
|
+
))
|
|
151
|
+
else
|
|
152
|
+
task.complete("Schema validation failed: #{schema_error}")
|
|
153
|
+
end
|
|
154
|
+
task
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def failed_task(error)
|
|
158
|
+
Phronomy::Task.deferred(name: "agent-tool-#{name}-failed").tap do |task|
|
|
159
|
+
task.fail(error)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def settle_async_error(task, error)
|
|
164
|
+
if error.is_a?(Phronomy::ToolError) || error.is_a?(Phronomy::CancellationError)
|
|
165
|
+
task.fail(error)
|
|
166
|
+
return task
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
if self.class.on_error == :suppress
|
|
170
|
+
message = "[Phronomy] Tool #{self.class.name} suppressed error: " \
|
|
171
|
+
"#{error.class}: #{error.message}"
|
|
172
|
+
if Phronomy.configuration.logger
|
|
173
|
+
Phronomy.configuration.logger.warn(message)
|
|
174
|
+
else
|
|
175
|
+
warn message
|
|
176
|
+
end
|
|
177
|
+
task.complete("Tool error suppressed: #{error.message}")
|
|
178
|
+
else
|
|
179
|
+
wrapped = Phronomy::ToolError.new(
|
|
180
|
+
"#{self.class.name} execution failed: #{error.message}"
|
|
181
|
+
)
|
|
182
|
+
wrapped.set_backtrace(error.backtrace)
|
|
183
|
+
task.fail(wrapped)
|
|
184
|
+
end
|
|
185
|
+
task
|
|
186
|
+
end
|
|
52
187
|
end
|
|
53
188
|
end
|
|
54
189
|
end
|
|
@@ -7,7 +7,7 @@ module Phronomy
|
|
|
7
7
|
# Mixing this module into a VectorStore class provides three choices:
|
|
8
8
|
#
|
|
9
9
|
# 1. **Do nothing** — inherits default implementations from {VectorStore::Base}
|
|
10
|
-
# that route through {
|
|
10
|
+
# that route through {OffloadPool}.
|
|
11
11
|
#
|
|
12
12
|
# 2. **Override selectively** — override only the async methods where the
|
|
13
13
|
# backend has a native async driver, while the remaining methods fall back
|
|
@@ -30,7 +30,7 @@ module Phronomy
|
|
|
30
30
|
module AsyncBackend
|
|
31
31
|
# Async variant of {VectorStore::Base#add}.
|
|
32
32
|
#
|
|
33
|
-
# Submits the add call to {
|
|
33
|
+
# Submits the add call to {OffloadPool} by default.
|
|
34
34
|
# Override to use a native async driver.
|
|
35
35
|
#
|
|
36
36
|
# @param id [String]
|
|
@@ -38,12 +38,13 @@ module Phronomy
|
|
|
38
38
|
# @param metadata [Hash]
|
|
39
39
|
# @param cancellation_token [Phronomy::Concurrency::CancellationToken, nil]
|
|
40
40
|
# @param timeout [Numeric, nil]
|
|
41
|
-
# @return [
|
|
41
|
+
# @return [OffloadPool::PendingOperation]
|
|
42
42
|
# @api public
|
|
43
43
|
def add_async(id:, embedding:, metadata: {}, cancellation_token: nil, timeout: nil)
|
|
44
|
-
Phronomy::Runtime.instance.
|
|
44
|
+
Phronomy::Runtime.instance.offload.submit(
|
|
45
45
|
timeout: timeout,
|
|
46
|
-
cancellation_token: cancellation_token
|
|
46
|
+
cancellation_token: cancellation_token,
|
|
47
|
+
on_full: :raise
|
|
47
48
|
) do
|
|
48
49
|
add(id: id, embedding: embedding, metadata: metadata, cancellation_token: cancellation_token)
|
|
49
50
|
end
|
|
@@ -51,19 +52,20 @@ module Phronomy
|
|
|
51
52
|
|
|
52
53
|
# Async variant of {VectorStore::Base#search}.
|
|
53
54
|
#
|
|
54
|
-
# Submits the search call to {
|
|
55
|
+
# Submits the search call to {OffloadPool} by default.
|
|
55
56
|
# Override to use a native async driver.
|
|
56
57
|
#
|
|
57
58
|
# @param query_embedding [Array<Float>]
|
|
58
59
|
# @param k [Integer]
|
|
59
60
|
# @param cancellation_token [Phronomy::Concurrency::CancellationToken, nil]
|
|
60
61
|
# @param timeout [Numeric, nil]
|
|
61
|
-
# @return [
|
|
62
|
+
# @return [OffloadPool::PendingOperation]
|
|
62
63
|
# @api public
|
|
63
64
|
def search_async(query_embedding:, k: 5, cancellation_token: nil, timeout: nil)
|
|
64
|
-
Phronomy::Runtime.instance.
|
|
65
|
+
Phronomy::Runtime.instance.offload.submit(
|
|
65
66
|
timeout: timeout,
|
|
66
|
-
cancellation_token: cancellation_token
|
|
67
|
+
cancellation_token: cancellation_token,
|
|
68
|
+
on_full: :raise
|
|
67
69
|
) do
|
|
68
70
|
search(query_embedding: query_embedding, k: k, cancellation_token: cancellation_token)
|
|
69
71
|
end
|
|
@@ -71,18 +73,19 @@ module Phronomy
|
|
|
71
73
|
|
|
72
74
|
# Async variant of {VectorStore::Base#remove}.
|
|
73
75
|
#
|
|
74
|
-
# Submits the remove call to {
|
|
76
|
+
# Submits the remove call to {OffloadPool} by default.
|
|
75
77
|
# Override to use a native async driver.
|
|
76
78
|
#
|
|
77
79
|
# @param id [String]
|
|
78
80
|
# @param cancellation_token [Phronomy::Concurrency::CancellationToken, nil]
|
|
79
81
|
# @param timeout [Numeric, nil]
|
|
80
|
-
# @return [
|
|
82
|
+
# @return [OffloadPool::PendingOperation]
|
|
81
83
|
# @api public
|
|
82
84
|
def remove_async(id:, cancellation_token: nil, timeout: nil)
|
|
83
|
-
Phronomy::Runtime.instance.
|
|
85
|
+
Phronomy::Runtime.instance.offload.submit(
|
|
84
86
|
timeout: timeout,
|
|
85
|
-
cancellation_token: cancellation_token
|
|
87
|
+
cancellation_token: cancellation_token,
|
|
88
|
+
on_full: :raise
|
|
86
89
|
) do
|
|
87
90
|
remove(id: id)
|
|
88
91
|
end
|
|
@@ -90,17 +93,18 @@ module Phronomy
|
|
|
90
93
|
|
|
91
94
|
# Async variant of {VectorStore::Base#clear}.
|
|
92
95
|
#
|
|
93
|
-
# Submits the clear call to {
|
|
96
|
+
# Submits the clear call to {OffloadPool} by default.
|
|
94
97
|
# Override to use a native async driver.
|
|
95
98
|
#
|
|
96
99
|
# @param cancellation_token [Phronomy::Concurrency::CancellationToken, nil]
|
|
97
100
|
# @param timeout [Numeric, nil]
|
|
98
|
-
# @return [
|
|
101
|
+
# @return [OffloadPool::PendingOperation]
|
|
99
102
|
# @api public
|
|
100
103
|
def clear_async(cancellation_token: nil, timeout: nil)
|
|
101
|
-
Phronomy::Runtime.instance.
|
|
104
|
+
Phronomy::Runtime.instance.offload.submit(
|
|
102
105
|
timeout: timeout,
|
|
103
|
-
cancellation_token: cancellation_token
|
|
106
|
+
cancellation_token: cancellation_token,
|
|
107
|
+
on_full: :raise
|
|
104
108
|
) do
|
|
105
109
|
clear
|
|
106
110
|
end
|
|
@@ -9,8 +9,8 @@ module Phronomy
|
|
|
9
9
|
#
|
|
10
10
|
# Async methods (`search_async`, `add_async`, `remove_async`, `clear_async`)
|
|
11
11
|
# are provided by the {AsyncBackend} mixin which defaults to routing calls
|
|
12
|
-
# through {
|
|
13
|
-
#
|
|
12
|
+
# through {OffloadPool}. Backends with native async drivers may override
|
|
13
|
+
# individual async methods without touching the pool at all.
|
|
14
14
|
class Base
|
|
15
15
|
include AsyncBackend
|
|
16
16
|
|
|
@@ -19,18 +19,19 @@ module Phronomy
|
|
|
19
19
|
raise NotImplementedError, "#{self.class}#embed is not implemented"
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
# Submits an {#embed} call to {
|
|
23
|
-
# {
|
|
22
|
+
# Submits an {#embed} call to {OffloadPool} and returns an
|
|
23
|
+
# {OffloadPool::PendingOperation}.
|
|
24
24
|
#
|
|
25
25
|
# @param text [String]
|
|
26
26
|
# @param cancellation_token [Phronomy::Concurrency::CancellationToken, nil]
|
|
27
27
|
# @param timeout [Numeric, nil] seconds before the operation is abandoned
|
|
28
|
-
# @return [
|
|
28
|
+
# @return [OffloadPool::PendingOperation]
|
|
29
29
|
# @api public
|
|
30
30
|
def embed_async(text, cancellation_token = nil, timeout: nil)
|
|
31
|
-
Phronomy::Runtime.instance.
|
|
31
|
+
Phronomy::Runtime.instance.offload.submit(
|
|
32
32
|
timeout: timeout,
|
|
33
|
-
cancellation_token: cancellation_token
|
|
33
|
+
cancellation_token: cancellation_token,
|
|
34
|
+
on_full: :raise
|
|
34
35
|
) do
|
|
35
36
|
embed(text, cancellation_token)
|
|
36
37
|
end
|
data/lib/phronomy/version.rb
CHANGED
data/lib/phronomy/workflow.rb
CHANGED
|
@@ -8,8 +8,8 @@ module Phronomy
|
|
|
8
8
|
class Workflow
|
|
9
9
|
include Phronomy::Runnable
|
|
10
10
|
|
|
11
|
-
def self.define(context_class,
|
|
12
|
-
builder = Builder.new(context_class,
|
|
11
|
+
def self.define(context_class, persistence: nil, &block)
|
|
12
|
+
builder = Builder.new(context_class, persistence: persistence)
|
|
13
13
|
builder.instance_eval(&block)
|
|
14
14
|
builder.build
|
|
15
15
|
end
|
|
@@ -41,12 +41,13 @@ module Phronomy
|
|
|
41
41
|
@runner.send_event(state: state, event: event, input: input)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
# Sends an event to an active Workflow
|
|
44
|
+
# Sends an event to an active Workflow execution without blocking.
|
|
45
45
|
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
46
|
+
# +thread_id+ is the logical/durable Workflow identity. EventLoop resolves it
|
|
47
|
+
# to the currently owning Runtime-only fsm_session_id. InvocationContext's
|
|
48
|
+
# application session_id is unrelated to this routing.
|
|
48
49
|
#
|
|
49
|
-
# @return [Boolean] true when admitted; false when the
|
|
50
|
+
# @return [Boolean] true when admitted; false when the Workflow is not live
|
|
50
51
|
# or Runtime shutdown has begun
|
|
51
52
|
# @api public
|
|
52
53
|
def signal(thread_id:, event:, payload: nil)
|
|
@@ -76,9 +77,9 @@ module Phronomy
|
|
|
76
77
|
class Builder
|
|
77
78
|
FINISH = Phronomy::WorkflowRunner::FINISH
|
|
78
79
|
|
|
79
|
-
def initialize(context_class,
|
|
80
|
+
def initialize(context_class, persistence: nil)
|
|
80
81
|
@context_class = context_class
|
|
81
|
-
@
|
|
82
|
+
@persistence = persistence
|
|
82
83
|
@initial = nil
|
|
83
84
|
@declared_states = []
|
|
84
85
|
@entry_actions = {}
|
|
@@ -167,7 +168,7 @@ module Phronomy
|
|
|
167
168
|
external_events: external_events,
|
|
168
169
|
entry_point: @initial || @declared_states.first,
|
|
169
170
|
wait_state_names: @wait_state_names.dup,
|
|
170
|
-
|
|
171
|
+
persistence: @persistence
|
|
171
172
|
)
|
|
172
173
|
Workflow.new(runner)
|
|
173
174
|
end
|