conductor_ruby 0.1.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 +7 -0
- data/CHANGELOG.md +142 -0
- data/LICENSE +190 -0
- data/README.md +517 -0
- data/examples/agentic_workflows/llm_chat.rb +106 -0
- data/examples/dynamic_workflow.rb +177 -0
- data/examples/event_handler.rb +94 -0
- data/examples/event_listener_examples.rb +430 -0
- data/examples/helloworld/greetings_worker.rb +24 -0
- data/examples/helloworld/helloworld.rb +99 -0
- data/examples/kitchensink.rb +213 -0
- data/examples/metadata_journey.rb +189 -0
- data/examples/metrics_example.rb +284 -0
- data/examples/new_dsl_demo.rb +141 -0
- data/examples/orkes/http_poll.rb +83 -0
- data/examples/orkes/secrets_example.rb +69 -0
- data/examples/orkes/wait_for_webhook.rb +90 -0
- data/examples/prompt_journey.rb +245 -0
- data/examples/rag_workflow.rb +167 -0
- data/examples/schedule_journey.rb +244 -0
- data/examples/simple_worker.rb +125 -0
- data/examples/simple_workflow.rb +89 -0
- data/examples/task_context_example.rb +257 -0
- data/examples/task_listener_example.rb +192 -0
- data/examples/worker_configuration_example.rb +282 -0
- data/examples/workflow_dsl.rb +316 -0
- data/examples/workflow_ops.rb +305 -0
- data/lib/conductor/client/authorization_client.rb +238 -0
- data/lib/conductor/client/integration_client.rb +108 -0
- data/lib/conductor/client/metadata_client.rb +139 -0
- data/lib/conductor/client/prompt_client.rb +58 -0
- data/lib/conductor/client/scheduler_client.rb +132 -0
- data/lib/conductor/client/schema_client.rb +32 -0
- data/lib/conductor/client/secret_client.rb +48 -0
- data/lib/conductor/client/task_client.rb +168 -0
- data/lib/conductor/client/workflow_client.rb +242 -0
- data/lib/conductor/configuration/authentication_settings.rb +17 -0
- data/lib/conductor/configuration.rb +103 -0
- data/lib/conductor/exceptions.rb +86 -0
- data/lib/conductor/http/api/application_resource_api.rb +107 -0
- data/lib/conductor/http/api/authorization_resource_api.rb +56 -0
- data/lib/conductor/http/api/event_resource_api.rb +133 -0
- data/lib/conductor/http/api/gateway_auth_resource_api.rb +48 -0
- data/lib/conductor/http/api/group_resource_api.rb +76 -0
- data/lib/conductor/http/api/integration_resource_api.rb +145 -0
- data/lib/conductor/http/api/metadata_resource_api.rb +231 -0
- data/lib/conductor/http/api/prompt_resource_api.rb +81 -0
- data/lib/conductor/http/api/role_resource_api.rb +60 -0
- data/lib/conductor/http/api/scheduler_resource_api.rb +211 -0
- data/lib/conductor/http/api/schema_resource_api.rb +82 -0
- data/lib/conductor/http/api/secret_resource_api.rb +134 -0
- data/lib/conductor/http/api/task_resource_api.rb +321 -0
- data/lib/conductor/http/api/token_resource_api.rb +42 -0
- data/lib/conductor/http/api/user_resource_api.rb +59 -0
- data/lib/conductor/http/api/workflow_bulk_resource_api.rb +91 -0
- data/lib/conductor/http/api/workflow_resource_api.rb +451 -0
- data/lib/conductor/http/api_client.rb +437 -0
- data/lib/conductor/http/models/authentication_config.rb +67 -0
- data/lib/conductor/http/models/authorization_request.rb +39 -0
- data/lib/conductor/http/models/base_model.rb +162 -0
- data/lib/conductor/http/models/bulk_response.rb +39 -0
- data/lib/conductor/http/models/conductor_application.rb +39 -0
- data/lib/conductor/http/models/conductor_user.rb +53 -0
- data/lib/conductor/http/models/create_or_update_application_request.rb +24 -0
- data/lib/conductor/http/models/create_or_update_role_request.rb +27 -0
- data/lib/conductor/http/models/event_handler.rb +130 -0
- data/lib/conductor/http/models/generate_token_request.rb +27 -0
- data/lib/conductor/http/models/group.rb +36 -0
- data/lib/conductor/http/models/integration.rb +70 -0
- data/lib/conductor/http/models/integration_api.rb +53 -0
- data/lib/conductor/http/models/integration_api_update.rb +43 -0
- data/lib/conductor/http/models/integration_update.rb +36 -0
- data/lib/conductor/http/models/permission.rb +24 -0
- data/lib/conductor/http/models/poll_data.rb +33 -0
- data/lib/conductor/http/models/prompt_template.rb +59 -0
- data/lib/conductor/http/models/prompt_template_test_request.rb +43 -0
- data/lib/conductor/http/models/rerun_workflow_request.rb +37 -0
- data/lib/conductor/http/models/role.rb +27 -0
- data/lib/conductor/http/models/schema_def.rb +59 -0
- data/lib/conductor/http/models/search_result.rb +187 -0
- data/lib/conductor/http/models/skip_task_request.rb +27 -0
- data/lib/conductor/http/models/start_workflow_request.rb +68 -0
- data/lib/conductor/http/models/subject_ref.rb +35 -0
- data/lib/conductor/http/models/tag_object.rb +36 -0
- data/lib/conductor/http/models/target_ref.rb +39 -0
- data/lib/conductor/http/models/task.rb +156 -0
- data/lib/conductor/http/models/task_def.rb +95 -0
- data/lib/conductor/http/models/task_exec_log.rb +30 -0
- data/lib/conductor/http/models/task_result.rb +115 -0
- data/lib/conductor/http/models/task_result_status.rb +24 -0
- data/lib/conductor/http/models/token.rb +33 -0
- data/lib/conductor/http/models/upsert_group_request.rb +30 -0
- data/lib/conductor/http/models/upsert_user_request.rb +39 -0
- data/lib/conductor/http/models/workflow.rb +202 -0
- data/lib/conductor/http/models/workflow_def.rb +73 -0
- data/lib/conductor/http/models/workflow_schedule.rb +100 -0
- data/lib/conductor/http/models/workflow_state_update.rb +30 -0
- data/lib/conductor/http/models/workflow_status_constants.rb +57 -0
- data/lib/conductor/http/models/workflow_task.rb +169 -0
- data/lib/conductor/http/models/workflow_test_request.rb +67 -0
- data/lib/conductor/http/rest_client.rb +211 -0
- data/lib/conductor/orkes/models/access_key.rb +56 -0
- data/lib/conductor/orkes/models/granted_permission.rb +27 -0
- data/lib/conductor/orkes/models/metadata_tag.rb +15 -0
- data/lib/conductor/orkes/models/rate_limit_tag.rb +15 -0
- data/lib/conductor/orkes/orkes_clients.rb +69 -0
- data/lib/conductor/version.rb +5 -0
- data/lib/conductor/worker/events/conductor_event.rb +40 -0
- data/lib/conductor/worker/events/global_dispatcher.rb +37 -0
- data/lib/conductor/worker/events/http_events.rb +25 -0
- data/lib/conductor/worker/events/listener_registry.rb +40 -0
- data/lib/conductor/worker/events/listeners.rb +34 -0
- data/lib/conductor/worker/events/sync_event_dispatcher.rb +78 -0
- data/lib/conductor/worker/events/task_runner_events.rb +271 -0
- data/lib/conductor/worker/events/workflow_events.rb +49 -0
- data/lib/conductor/worker/fiber_executor.rb +532 -0
- data/lib/conductor/worker/ractor_task_runner.rb +501 -0
- data/lib/conductor/worker/task_context.rb +114 -0
- data/lib/conductor/worker/task_definition_registrar.rb +322 -0
- data/lib/conductor/worker/task_handler.rb +360 -0
- data/lib/conductor/worker/task_in_progress.rb +60 -0
- data/lib/conductor/worker/task_runner.rb +538 -0
- data/lib/conductor/worker/telemetry/metrics_collector.rb +196 -0
- data/lib/conductor/worker/telemetry/prometheus_backend.rb +224 -0
- data/lib/conductor/worker/worker.rb +355 -0
- data/lib/conductor/worker/worker_config.rb +154 -0
- data/lib/conductor/worker/worker_registry.rb +71 -0
- data/lib/conductor/workflow/dsl/input_ref.rb +37 -0
- data/lib/conductor/workflow/dsl/output_ref.rb +44 -0
- data/lib/conductor/workflow/dsl/parallel_builder.rb +49 -0
- data/lib/conductor/workflow/dsl/switch_builder.rb +74 -0
- data/lib/conductor/workflow/dsl/task_ref.rb +178 -0
- data/lib/conductor/workflow/dsl/workflow_builder.rb +1016 -0
- data/lib/conductor/workflow/dsl/workflow_definition.rb +150 -0
- data/lib/conductor/workflow/llm/chat_message.rb +47 -0
- data/lib/conductor/workflow/llm/embedding_model.rb +19 -0
- data/lib/conductor/workflow/llm/tool_call.rb +43 -0
- data/lib/conductor/workflow/llm/tool_spec.rb +46 -0
- data/lib/conductor/workflow/task_type.rb +68 -0
- data/lib/conductor/workflow/timeout_policy.rb +31 -0
- data/lib/conductor/workflow/workflow_executor.rb +373 -0
- data/lib/conductor.rb +192 -0
- metadata +359 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Greetings Worker
|
|
4
|
+
# ================
|
|
5
|
+
# Simple worker that creates a greeting message.
|
|
6
|
+
# For detailed explanation: https://github.com/conductor-oss/ruby-sdk
|
|
7
|
+
|
|
8
|
+
require_relative '../../lib/conductor'
|
|
9
|
+
|
|
10
|
+
# Worker that creates a greeting message
|
|
11
|
+
class GreetingsWorker
|
|
12
|
+
include Conductor::Worker::WorkerModule
|
|
13
|
+
|
|
14
|
+
worker_task 'greet'
|
|
15
|
+
|
|
16
|
+
def execute(task)
|
|
17
|
+
name = get_input(task, 'name', 'World')
|
|
18
|
+
greeting = "Hello, #{name}!"
|
|
19
|
+
|
|
20
|
+
puts "[GreetingsWorker] Created greeting: #{greeting}"
|
|
21
|
+
|
|
22
|
+
{ 'result' => greeting }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Hello World Example
|
|
5
|
+
# ===================
|
|
6
|
+
#
|
|
7
|
+
# The simplest complete example demonstrating:
|
|
8
|
+
# 1. Define a workflow using the new Ruby-idiomatic DSL
|
|
9
|
+
# 2. Register the workflow
|
|
10
|
+
# 3. Start workers
|
|
11
|
+
# 4. Execute the workflow
|
|
12
|
+
# 5. Get the result
|
|
13
|
+
#
|
|
14
|
+
# Usage:
|
|
15
|
+
# cd examples/helloworld
|
|
16
|
+
# bundle exec ruby helloworld.rb
|
|
17
|
+
#
|
|
18
|
+
# Prerequisites:
|
|
19
|
+
# - Conductor server running (set CONDUCTOR_SERVER_URL env var)
|
|
20
|
+
# - For Orkes: Set CONDUCTOR_AUTH_KEY and CONDUCTOR_AUTH_SECRET
|
|
21
|
+
|
|
22
|
+
require_relative 'greetings_worker'
|
|
23
|
+
|
|
24
|
+
def create_greetings_workflow(executor)
|
|
25
|
+
# Define workflow using the new Ruby-idiomatic DSL
|
|
26
|
+
Conductor.workflow :greetings, version: 1, executor: executor do
|
|
27
|
+
# Create greet task that uses workflow input
|
|
28
|
+
# wf[:name] returns "${workflow.input.name}"
|
|
29
|
+
greet = simple :greet, name: wf[:name]
|
|
30
|
+
|
|
31
|
+
# Set output to be the result from greet task
|
|
32
|
+
# greet[:result] returns "${greet_ref.output.result}"
|
|
33
|
+
output result: greet[:result]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def main
|
|
38
|
+
# Configuration - reads from environment variables by default:
|
|
39
|
+
# CONDUCTOR_SERVER_URL: Conductor server URL (default: http://localhost:8080/api)
|
|
40
|
+
# CONDUCTOR_AUTH_KEY: API Authentication Key (optional for OSS)
|
|
41
|
+
# CONDUCTOR_AUTH_SECRET: API Auth Secret (optional for OSS)
|
|
42
|
+
config = Conductor::Configuration.new
|
|
43
|
+
|
|
44
|
+
puts '=' * 60
|
|
45
|
+
puts 'Conductor Ruby SDK - Hello World'
|
|
46
|
+
puts '=' * 60
|
|
47
|
+
puts
|
|
48
|
+
puts "Server: #{config.server_url}"
|
|
49
|
+
puts
|
|
50
|
+
|
|
51
|
+
# Create clients
|
|
52
|
+
clients = Conductor::Orkes::OrkesClients.new(config)
|
|
53
|
+
workflow_executor = clients.get_workflow_executor
|
|
54
|
+
|
|
55
|
+
# Create workflow with executor (required for register/execute)
|
|
56
|
+
workflow = create_greetings_workflow(workflow_executor)
|
|
57
|
+
|
|
58
|
+
# Register workflow (only needs to be done once)
|
|
59
|
+
puts 'Registering workflow...'
|
|
60
|
+
workflow.register(overwrite: true)
|
|
61
|
+
puts "Registered workflow: #{workflow.name} v#{workflow.version}"
|
|
62
|
+
puts
|
|
63
|
+
|
|
64
|
+
# Start workers
|
|
65
|
+
puts 'Starting workers...'
|
|
66
|
+
task_handler = Conductor::Worker::TaskRunner.new(config)
|
|
67
|
+
task_handler.register_worker(GreetingsWorker.new)
|
|
68
|
+
task_handler.start
|
|
69
|
+
puts 'Workers started!'
|
|
70
|
+
puts
|
|
71
|
+
|
|
72
|
+
# Execute workflow using the new DSL's execute method
|
|
73
|
+
puts 'Executing workflow with input: { name: "World" }'
|
|
74
|
+
workflow_run = workflow.execute(input: { 'name' => 'World' }, wait_for_seconds: 30)
|
|
75
|
+
|
|
76
|
+
puts
|
|
77
|
+
puts '-' * 60
|
|
78
|
+
puts "Workflow result: #{workflow_run.output['result']}"
|
|
79
|
+
puts '-' * 60
|
|
80
|
+
puts
|
|
81
|
+
puts "See the workflow execution at: #{config.ui_host}/execution/#{workflow_run.workflow_id}"
|
|
82
|
+
|
|
83
|
+
# Stop workers
|
|
84
|
+
task_handler.stop
|
|
85
|
+
puts
|
|
86
|
+
puts 'Done!'
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
if __FILE__ == $PROGRAM_NAME
|
|
90
|
+
begin
|
|
91
|
+
main
|
|
92
|
+
rescue Conductor::ApiError => e
|
|
93
|
+
puts "API Error: #{e.message}"
|
|
94
|
+
puts e.backtrace.first(5).join("\n")
|
|
95
|
+
rescue StandardError => e
|
|
96
|
+
puts "Error: #{e.message}"
|
|
97
|
+
puts e.backtrace.first(5).join("\n")
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Kitchen Sink Example
|
|
5
|
+
# ====================
|
|
6
|
+
#
|
|
7
|
+
# Comprehensive example demonstrating all major workflow task types and patterns
|
|
8
|
+
# using the new Ruby-idiomatic DSL.
|
|
9
|
+
#
|
|
10
|
+
# What it demonstrates:
|
|
11
|
+
# ---------------------
|
|
12
|
+
# - simple() - Custom worker tasks
|
|
13
|
+
# - http() - External API calls
|
|
14
|
+
# - javascript() - Inline JavaScript execution
|
|
15
|
+
# - jq() - JSON transformation with JQ
|
|
16
|
+
# - decide() - Conditional branching (switch)
|
|
17
|
+
# - wait() - Pause workflow execution
|
|
18
|
+
# - set() - Store workflow variables
|
|
19
|
+
# - terminate() - End workflow with specific status
|
|
20
|
+
# - sub_workflow() - Call another workflow
|
|
21
|
+
# - parallel() - Concurrent task execution
|
|
22
|
+
#
|
|
23
|
+
# Usage:
|
|
24
|
+
# bundle exec ruby examples/kitchensink.rb
|
|
25
|
+
|
|
26
|
+
require_relative '../lib/conductor'
|
|
27
|
+
|
|
28
|
+
# ============================================================================
|
|
29
|
+
# WORKER - Custom task implementation
|
|
30
|
+
# ============================================================================
|
|
31
|
+
|
|
32
|
+
class RouteWorker
|
|
33
|
+
include Conductor::Worker::WorkerModule
|
|
34
|
+
|
|
35
|
+
worker_task 'route'
|
|
36
|
+
|
|
37
|
+
def execute(task)
|
|
38
|
+
country = get_input(task, 'country', 'Unknown')
|
|
39
|
+
message = "routing the packages to #{country}"
|
|
40
|
+
puts "[RouteWorker] #{message}"
|
|
41
|
+
{ 'result' => message }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def start_workers(config)
|
|
46
|
+
task_handler = Conductor::Worker::TaskRunner.new(config)
|
|
47
|
+
task_handler.register_worker(RouteWorker.new)
|
|
48
|
+
task_handler.start
|
|
49
|
+
task_handler
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def create_sub_workflow(executor)
|
|
53
|
+
# Create a sub-workflow that will be called from the main workflow
|
|
54
|
+
Conductor.workflow :sub_ruby, version: 1, executor: executor do
|
|
55
|
+
# HTTP call using workflow input for URI
|
|
56
|
+
http :sub_call_api, url: wf[:uri]
|
|
57
|
+
|
|
58
|
+
# Wait for 2 seconds
|
|
59
|
+
wait 2
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def create_kitchensink_workflow(executor)
|
|
64
|
+
# Main kitchen sink workflow using the new DSL
|
|
65
|
+
Conductor.workflow :kitchensink_ruby, version: 1, executor: executor do
|
|
66
|
+
# -------------------------------------------------------------------------
|
|
67
|
+
# 1. JavaScript Task - Execute inline JavaScript
|
|
68
|
+
# -------------------------------------------------------------------------
|
|
69
|
+
say_hello_js = <<~JS
|
|
70
|
+
function greetings() {
|
|
71
|
+
return {
|
|
72
|
+
"text": "hello " + $.name,
|
|
73
|
+
"url": "https://orkes-api-tester.orkesconductor.com/api"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
greetings();
|
|
77
|
+
JS
|
|
78
|
+
|
|
79
|
+
js = javascript :hello_script, script: say_hello_js, name: wf[:name]
|
|
80
|
+
|
|
81
|
+
# -------------------------------------------------------------------------
|
|
82
|
+
# 2. Parallel Execution - HTTP call and sub-workflow run concurrently
|
|
83
|
+
# -------------------------------------------------------------------------
|
|
84
|
+
parallel do
|
|
85
|
+
# Branch 1: Call sub-workflow with URL from JS task
|
|
86
|
+
sub_workflow :call_sub_workflow, workflow: 'sub_ruby', version: 1, uri: js[:url]
|
|
87
|
+
|
|
88
|
+
# Branch 2: HTTP call followed by wait
|
|
89
|
+
http :call_remote_api, url: 'https://orkes-api-tester.orkesconductor.com/api'
|
|
90
|
+
wait 2
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# -------------------------------------------------------------------------
|
|
94
|
+
# 3. JSON JQ Task - Transform JSON data
|
|
95
|
+
# -------------------------------------------------------------------------
|
|
96
|
+
jq :jq_process,
|
|
97
|
+
query: '{ key3: (.key1.value1 + .key2.value2) }',
|
|
98
|
+
key1: { 'value1' => %w[a b] },
|
|
99
|
+
key2: { 'value2' => %w[d e] }
|
|
100
|
+
|
|
101
|
+
# -------------------------------------------------------------------------
|
|
102
|
+
# 4. Set Variable Task - Store workflow variables
|
|
103
|
+
# -------------------------------------------------------------------------
|
|
104
|
+
set(
|
|
105
|
+
var1: 'value1',
|
|
106
|
+
var2: 42,
|
|
107
|
+
var3: %w[a b c]
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# -------------------------------------------------------------------------
|
|
111
|
+
# 5. Switch Task - Conditional branching based on country
|
|
112
|
+
# -------------------------------------------------------------------------
|
|
113
|
+
decide wf[:country] do
|
|
114
|
+
on 'US' do
|
|
115
|
+
simple :route, country: wf[:country]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
on 'CA' do
|
|
119
|
+
simple :route, country: wf[:country]
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
otherwise do
|
|
123
|
+
terminate :terminated, 'unsupported country'
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# -------------------------------------------------------------------------
|
|
128
|
+
# Set workflow output
|
|
129
|
+
# -------------------------------------------------------------------------
|
|
130
|
+
output greetings: js[:output]
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def main
|
|
135
|
+
# Configuration from environment variables
|
|
136
|
+
config = Conductor::Configuration.new
|
|
137
|
+
|
|
138
|
+
puts '=' * 70
|
|
139
|
+
puts 'Conductor Ruby SDK - Kitchen Sink Example (New DSL)'
|
|
140
|
+
puts '=' * 70
|
|
141
|
+
puts
|
|
142
|
+
puts "Server: #{config.server_url}"
|
|
143
|
+
puts
|
|
144
|
+
|
|
145
|
+
# Create clients
|
|
146
|
+
clients = Conductor::Orkes::OrkesClients.new(config)
|
|
147
|
+
workflow_executor = clients.get_workflow_executor
|
|
148
|
+
|
|
149
|
+
# Start workers
|
|
150
|
+
task_handler = start_workers(config)
|
|
151
|
+
puts 'Workers started...'
|
|
152
|
+
puts
|
|
153
|
+
|
|
154
|
+
# ============================================================================
|
|
155
|
+
# CREATE WORKFLOWS USING NEW DSL
|
|
156
|
+
# ============================================================================
|
|
157
|
+
|
|
158
|
+
sub_workflow = create_sub_workflow(workflow_executor)
|
|
159
|
+
main_workflow = create_kitchensink_workflow(workflow_executor)
|
|
160
|
+
|
|
161
|
+
# ============================================================================
|
|
162
|
+
# REGISTER SUB-WORKFLOW FIRST
|
|
163
|
+
# ============================================================================
|
|
164
|
+
|
|
165
|
+
puts 'Registering sub-workflow...'
|
|
166
|
+
sub_workflow.register(overwrite: true)
|
|
167
|
+
puts "Sub-workflow '#{sub_workflow.name}' registered!"
|
|
168
|
+
puts
|
|
169
|
+
|
|
170
|
+
# ============================================================================
|
|
171
|
+
# REGISTER AND EXECUTE MAIN WORKFLOW
|
|
172
|
+
# ============================================================================
|
|
173
|
+
|
|
174
|
+
puts 'Registering main workflow...'
|
|
175
|
+
main_workflow.register(overwrite: true)
|
|
176
|
+
puts "Main workflow '#{main_workflow.name}' registered!"
|
|
177
|
+
puts
|
|
178
|
+
|
|
179
|
+
puts 'Executing kitchen sink workflow...'
|
|
180
|
+
puts "Input: { name: 'Conductor Ruby', country: 'US' }"
|
|
181
|
+
puts
|
|
182
|
+
|
|
183
|
+
result = main_workflow.execute(
|
|
184
|
+
input: { 'name' => 'Conductor Ruby', 'country' => 'US' },
|
|
185
|
+
wait_for_seconds: 60
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
puts
|
|
189
|
+
puts 'Workflow completed!'
|
|
190
|
+
puts '-' * 70
|
|
191
|
+
puts "Workflow ID: #{result.workflow_id}"
|
|
192
|
+
puts "Status: #{result.status}"
|
|
193
|
+
puts "Output: #{result.output.inspect}"
|
|
194
|
+
puts
|
|
195
|
+
puts "See the execution at: #{config.ui_host}/execution/#{result.workflow_id}"
|
|
196
|
+
|
|
197
|
+
# Stop workers
|
|
198
|
+
task_handler.stop
|
|
199
|
+
puts
|
|
200
|
+
puts 'Workers stopped. Goodbye!'
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
if __FILE__ == $PROGRAM_NAME
|
|
204
|
+
begin
|
|
205
|
+
main
|
|
206
|
+
rescue Conductor::ApiError => e
|
|
207
|
+
puts "API Error: #{e.message}"
|
|
208
|
+
puts e.backtrace.first(5).join("\n")
|
|
209
|
+
rescue StandardError => e
|
|
210
|
+
puts "Error: #{e.message}"
|
|
211
|
+
puts e.backtrace.first(5).join("\n")
|
|
212
|
+
end
|
|
213
|
+
end
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Metadata Management Journey
|
|
5
|
+
#
|
|
6
|
+
# Demonstrates all metadata operations: workflow definitions,
|
|
7
|
+
# task definitions, and tagging.
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# bundle exec ruby examples/metadata_journey.rb
|
|
11
|
+
|
|
12
|
+
require_relative '../lib/conductor'
|
|
13
|
+
|
|
14
|
+
class MetadataJourney
|
|
15
|
+
def initialize
|
|
16
|
+
@config = Conductor::Configuration.new
|
|
17
|
+
@clients = Conductor::Orkes::OrkesClients.new(@config)
|
|
18
|
+
@metadata = @clients.get_metadata_client
|
|
19
|
+
|
|
20
|
+
puts '=' * 70
|
|
21
|
+
puts 'Metadata Management Journey'
|
|
22
|
+
puts '=' * 70
|
|
23
|
+
puts "Server: #{@config.server_url}"
|
|
24
|
+
puts
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def run
|
|
28
|
+
manage_task_definitions
|
|
29
|
+
manage_workflow_definitions
|
|
30
|
+
work_with_tags
|
|
31
|
+
cleanup
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def manage_task_definitions
|
|
37
|
+
puts "\n--- Task Definitions ---"
|
|
38
|
+
|
|
39
|
+
# Create task definitions
|
|
40
|
+
tasks = [
|
|
41
|
+
{
|
|
42
|
+
'name' => 'ruby_process_order',
|
|
43
|
+
'description' => 'Process incoming orders',
|
|
44
|
+
'retryCount' => 3,
|
|
45
|
+
'retryLogic' => 'FIXED',
|
|
46
|
+
'retryDelaySeconds' => 10,
|
|
47
|
+
'timeoutSeconds' => 300,
|
|
48
|
+
'responseTimeoutSeconds' => 60
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
'name' => 'ruby_send_notification',
|
|
52
|
+
'description' => 'Send customer notifications',
|
|
53
|
+
'retryCount' => 2,
|
|
54
|
+
'timeoutSeconds' => 60
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
'name' => 'ruby_update_inventory',
|
|
58
|
+
'description' => 'Update inventory counts',
|
|
59
|
+
'retryCount' => 5,
|
|
60
|
+
'timeoutSeconds' => 120
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
tasks.each do |task|
|
|
65
|
+
@metadata.register_task_def(task)
|
|
66
|
+
puts "Created task: #{task['name']}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Get a specific task
|
|
70
|
+
task = @metadata.get_task_def('ruby_process_order')
|
|
71
|
+
puts "\nRetrieved task: #{task['name'] || task.name}"
|
|
72
|
+
|
|
73
|
+
# Get all tasks
|
|
74
|
+
all_tasks = @metadata.get_all_task_defs
|
|
75
|
+
puts "Total tasks in system: #{all_tasks.length}"
|
|
76
|
+
|
|
77
|
+
@created_tasks = tasks.map { |t| t['name'] }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def manage_workflow_definitions
|
|
81
|
+
puts "\n--- Workflow Definitions ---"
|
|
82
|
+
|
|
83
|
+
# Create workflow definition
|
|
84
|
+
workflow_def = {
|
|
85
|
+
'name' => 'ruby_order_pipeline',
|
|
86
|
+
'description' => 'Complete order processing pipeline',
|
|
87
|
+
'version' => 1,
|
|
88
|
+
'schemaVersion' => 2,
|
|
89
|
+
'tasks' => [
|
|
90
|
+
{
|
|
91
|
+
'name' => 'ruby_process_order',
|
|
92
|
+
'taskReferenceName' => 'process_ref',
|
|
93
|
+
'type' => 'SIMPLE',
|
|
94
|
+
'inputParameters' => {
|
|
95
|
+
'orderId' => '${workflow.input.orderId}'
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
'name' => 'ruby_update_inventory',
|
|
100
|
+
'taskReferenceName' => 'inventory_ref',
|
|
101
|
+
'type' => 'SIMPLE',
|
|
102
|
+
'inputParameters' => {
|
|
103
|
+
'items' => '${process_ref.output.items}'
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
'name' => 'ruby_send_notification',
|
|
108
|
+
'taskReferenceName' => 'notify_ref',
|
|
109
|
+
'type' => 'SIMPLE',
|
|
110
|
+
'inputParameters' => {
|
|
111
|
+
'customerId' => '${workflow.input.customerId}',
|
|
112
|
+
'status' => '${inventory_ref.output.status}'
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
'outputParameters' => {
|
|
117
|
+
'orderStatus' => '${notify_ref.output.status}'
|
|
118
|
+
},
|
|
119
|
+
'timeoutSeconds' => 600
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
@metadata.register_workflow_def(workflow_def, overwrite: true)
|
|
123
|
+
puts "Created workflow: #{workflow_def['name']}"
|
|
124
|
+
|
|
125
|
+
# Get the workflow
|
|
126
|
+
wf = @metadata.get_workflow_def('ruby_order_pipeline')
|
|
127
|
+
puts "Retrieved workflow: #{wf['name'] || wf.name}"
|
|
128
|
+
|
|
129
|
+
# Get all workflows
|
|
130
|
+
all_workflows = @metadata.get_all_workflow_defs
|
|
131
|
+
puts "Total workflows in system: #{all_workflows.length}"
|
|
132
|
+
|
|
133
|
+
@created_workflow = workflow_def['name']
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def work_with_tags
|
|
137
|
+
puts "\n--- Working with Tags ---"
|
|
138
|
+
|
|
139
|
+
# Tag a workflow
|
|
140
|
+
tags = [
|
|
141
|
+
{ 'key' => 'team', 'value' => 'orders' },
|
|
142
|
+
{ 'key' => 'environment', 'value' => 'development' }
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
begin
|
|
146
|
+
@metadata.add_workflow_tag('ruby_order_pipeline', tags.first)
|
|
147
|
+
puts "Added tag to workflow: #{tags.first['key']}=#{tags.first['value']}"
|
|
148
|
+
|
|
149
|
+
# Get workflow tags
|
|
150
|
+
wf_tags = @metadata.get_workflow_tags('ruby_order_pipeline')
|
|
151
|
+
puts "Workflow tags: #{wf_tags.length}"
|
|
152
|
+
rescue StandardError => e
|
|
153
|
+
puts "Tag operations: #{e.message}"
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def cleanup
|
|
158
|
+
puts "\n--- Cleanup ---"
|
|
159
|
+
|
|
160
|
+
# Delete workflow
|
|
161
|
+
begin
|
|
162
|
+
@metadata.unregister_workflow_def(@created_workflow, 1)
|
|
163
|
+
puts "Deleted workflow: #{@created_workflow}"
|
|
164
|
+
rescue StandardError => e
|
|
165
|
+
puts "Could not delete workflow: #{e.message}"
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Delete tasks
|
|
169
|
+
@created_tasks&.each do |name|
|
|
170
|
+
@metadata.unregister_task_def(name)
|
|
171
|
+
puts "Deleted task: #{name}"
|
|
172
|
+
rescue StandardError => e
|
|
173
|
+
puts "Could not delete #{name}: #{e.message}"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
puts "\nMetadata journey complete!"
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
if __FILE__ == $PROGRAM_NAME
|
|
181
|
+
begin
|
|
182
|
+
MetadataJourney.new.run
|
|
183
|
+
rescue Conductor::ApiError => e
|
|
184
|
+
puts "API Error: #{e.message}"
|
|
185
|
+
rescue StandardError => e
|
|
186
|
+
puts "Error: #{e.message}"
|
|
187
|
+
puts e.backtrace.first(3).join("\n")
|
|
188
|
+
end
|
|
189
|
+
end
|