ruby_slm 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.
data/README.md ADDED
@@ -0,0 +1,768 @@
1
+ # Ruby State Language Machine (SLM)
2
+
3
+ A powerful, flexible state machine implementation for Ruby that's compatible with AWS Step Functions state language. Define complex workflows using YAML/JSON and execute them with local Ruby methods or external resources.
4
+
5
+ [![Ruby](https://img.shields.io/badge/Ruby-3.4+-red.svg)](https://ruby-lang.org)
6
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+
8
+ ## Features
9
+
10
+ - ๐Ÿš€ **AWS Step Functions Compatible** - Use the same state language as AWS Step Functions
11
+ - ๐Ÿ”„ https://states-language.net/
12
+ - ๐Ÿ”ง **Local Method Execution** - Execute Ruby methods directly from state tasks
13
+ - ๐Ÿ“ **YAML/JSON Support** - Define workflows in human-readable formats
14
+ - ๐Ÿ›ก๏ธ **Error Handling** - Built-in retry and catch mechanisms
15
+ - โฑ๏ธ **Timeout & Heartbeat** - Control task execution timing
16
+ - ๐Ÿ”„ **All State Types** - Support for Pass, Task, Choice, Parallel, Wait, Succeed, Fail
17
+ - ๐Ÿงช **Test-Friendly** - Easy to mock and test workflows
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ ```ruby
24
+ gem 'ruby_slm'
25
+ ```
26
+
27
+ And then execute:
28
+
29
+ ```bash
30
+ $ bundle install
31
+ ```
32
+ Quick Start
33
+
34
+ 1. Define Your Workflow
35
+ Create a YAML file (order_workflow.yaml):
36
+ ```yaml
37
+ Comment: Order Processing Workflow
38
+ StartAt: ValidateOrder
39
+ States:
40
+ ValidateOrder:
41
+ Type: Task
42
+ Resource: method:validate_order
43
+ Next: ProcessPayment
44
+ ResultPath: $.validation_result
45
+
46
+ ProcessPayment:
47
+ Type: Task
48
+ Resource: method:process_payment
49
+ Next: UpdateInventory
50
+ ResultPath: $.payment_result
51
+ Catch:
52
+ - ErrorEquals: ["States.ALL"]
53
+ Next: HandlePaymentFailure
54
+ ResultPath: $.error_info
55
+
56
+ HandlePaymentFailure:
57
+ Type: Task
58
+ Resource: method:handle_payment_failure
59
+ End: true
60
+
61
+ UpdateInventory:
62
+ Type: Task
63
+ Resource: method:update_inventory
64
+ Next: SendConfirmation
65
+ ResultPath: $.inventory_result
66
+
67
+ SendConfirmation:
68
+ Type: Task
69
+ Resource: method:send_confirmation
70
+ End: true
71
+ ResultPath: $.confirmation_result
72
+ ```
73
+
74
+ 2. Implement Your Business Logic
75
+ ```ruby
76
+ class OrderProcessor
77
+ def validate_order(input)
78
+ order = input['order']
79
+ {
80
+ "valid" => true,
81
+ "order_id" => order['id'],
82
+ "customer_id" => order['customer_id']
83
+ }
84
+ end
85
+
86
+ def process_payment(input)
87
+ {
88
+ "payment_status" => "completed",
89
+ "payment_id" => "pay_#{SecureRandom.hex(8)}",
90
+ "amount_charged" => input['order']['total']
91
+ }
92
+ end
93
+
94
+ def update_inventory(input)
95
+ {
96
+ "inventory_updated" => true,
97
+ "order_id" => input['order']['id']
98
+ }
99
+ end
100
+
101
+ def send_confirmation(input)
102
+ {
103
+ "confirmation_sent" => true,
104
+ "order_id" => input['order']['id']
105
+ }
106
+ end
107
+
108
+ def handle_payment_failure(input)
109
+ {
110
+ "payment_failure_handled" => true,
111
+ "order_id" => input['order']['id']
112
+ }
113
+ end
114
+ end
115
+ ```
116
+
117
+ 3. Execute the Workflow
118
+ ```ruby
119
+ require 'ruby_slm'
120
+
121
+ # Create your business logic processor
122
+ processor = OrderProcessor.new
123
+
124
+ # Create an executor that routes to local methods
125
+ executor = ->(resource, input, credentials) do
126
+ method_name = resource.sub('method:', '')
127
+ processor.send(method_name, input)
128
+ end
129
+
130
+ # Load and execute the workflow
131
+ state_machine = StatesLanguageMachine.from_yaml_file('order_workflow.yaml')
132
+
133
+ input = {
134
+ "order" => {
135
+ "id" => "ORD-123",
136
+ "total" => 99.99,
137
+ "customer_id" => "CUST-456"
138
+ }
139
+ }
140
+
141
+ execution = state_machine.start_execution(input, "my-order-execution")
142
+ execution.context[:task_executor] = executor
143
+ execution.run_all
144
+
145
+ puts "Status: #{execution.status}" # => "succeeded"
146
+ puts "Output: #{execution.output}"
147
+ ```
148
+
149
+ ## State Types
150
+ ### Task State
151
+ #### Execute work using local methods or external resources.
152
+
153
+ ```yaml
154
+ ProcessData:
155
+ Type: Task
156
+ Resource: method:process_data
157
+ Next: NextState
158
+ TimeoutSeconds: 300
159
+ Retry:
160
+ - ErrorEquals: ["States.Timeout"]
161
+ IntervalSeconds: 5
162
+ MaxAttempts: 3
163
+ Catch:
164
+ - ErrorEquals: ["States.ALL"]
165
+ Next: HandleError
166
+ ResultPath: $.processing_result
167
+ ```
168
+
169
+ ### Pass State
170
+ #### Transform data without performing work.
171
+ ```yaml
172
+ TransformData:
173
+ Type: Pass
174
+ Parameters:
175
+ original_id.$: $.order.id
176
+ processed_at: 1698765432
177
+ status: "processing"
178
+ ResultPath: $.metadata
179
+ Next: NextState
180
+ ```
181
+
182
+ ### Choice State
183
+ #### Make decisions based on data.
184
+ ```yaml
185
+ CheckInventory:
186
+ Type: Choice
187
+ Choices:
188
+ - Variable: $.inventory.available
189
+ BooleanEquals: true
190
+ Next: ProcessOrder
191
+ - Variable: $.order.priority
192
+ StringEquals: "high"
193
+ Next: ExpediteOrder
194
+ Default: WaitForStock
195
+ ```
196
+
197
+ ### Parallel State
198
+ #### Execute multiple branches concurrently.
199
+ ```yaml
200
+ ProcessInParallel:
201
+ Type: Parallel
202
+ Branches:
203
+ - StartAt: UpdateInventory
204
+ States: { ... }
205
+ - StartAt: NotifyCustomer
206
+ States: { ... }
207
+ Next: AggregateResults
208
+ ```
209
+
210
+ ### Wait State
211
+ #### Wait for a specified time or until a timestamp.
212
+
213
+ ```yaml
214
+ WaitForPayment:
215
+ Type: Wait
216
+ Seconds: 300
217
+ Next: CheckPaymentStatus
218
+ `````
219
+
220
+ ### Succeed & Fail States
221
+ #### Terminate execution successfully or with error.
222
+
223
+ ```yaml
224
+ OrderCompleted:
225
+ Type: Succeed
226
+
227
+ OrderFailed:
228
+ Type: Fail
229
+ Cause: "Payment processing failed"
230
+ Error: "PaymentError"
231
+ ```
232
+
233
+ ## Advanced Features
234
+
235
+ ### Retry Mechanisms
236
+
237
+ ```yaml
238
+ CallExternalAPI:
239
+ Type: Task
240
+ Resource: method:call_external_api
241
+ Retry:
242
+ - ErrorEquals: ["States.Timeout", "NetworkError"]
243
+ IntervalSeconds: 1
244
+ MaxAttempts: 5
245
+ BackoffRate: 2.0
246
+ - ErrorEquals: ["RateLimitExceeded"]
247
+ IntervalSeconds: 60
248
+ MaxAttempts: 3
249
+ Next: NextState
250
+ ```
251
+ ### Input/Output Processing
252
+
253
+ ```yaml
254
+ ProcessOrder:
255
+ Type: Task
256
+ Resource: method:process_order
257
+ InputPath: $.order_data
258
+ OutputPath: $.result
259
+ ResultPath: $.processing_result
260
+ ResultSelector:
261
+ success: true
262
+ processed_at: 1698765432
263
+ order_id.$: $.order.id
264
+ ```
265
+
266
+ ### Intrinsic Functions
267
+ ```yaml
268
+ FormatMessage:
269
+ Type: Pass
270
+ Parameters:
271
+ message: "States.Format('Hello {}, your order {} is ready!', $.customer.name, $.order.id)"
272
+ uuid: "States.UUID()"
273
+ random_number: "States.MathRandom(1, 100)"
274
+ ResultPath: $.formatted_data
275
+ ```
276
+
277
+ ### Local Method Execution
278
+ #### Method Routing
279
+
280
+ ```ruby
281
+ class BusinessLogic
282
+ def process_data(input)
283
+ # Your business logic here
284
+ { "processed" => true, "result" => input.transform_values(&:upcase) }
285
+ end
286
+
287
+ def validate_input(input)
288
+ # Validation logic
289
+ raise "Invalid input" unless input['required_field']
290
+ { "valid" => true }
291
+ end
292
+ end
293
+
294
+ # Create executor
295
+ logic = BusinessLogic.new
296
+ executor = ->(resource, input, credentials) do
297
+ method_name = resource.sub('method:', '')
298
+ logic.send(method_name, input)
299
+ end
300
+
301
+ # Use in execution context
302
+ execution.context[:task_executor] = executor
303
+
304
+ ```
305
+ #### Custom Executors
306
+
307
+ ```ruby
308
+ class CustomExecutor
309
+ def call(resource, input, credentials)
310
+ case resource
311
+ when /^method:/
312
+ execute_local_method(resource, input)
313
+ when /^arn:aws:lambda:/
314
+ execute_lambda(resource, input, credentials)
315
+ when /^arn:aws:sqs:/
316
+ send_sqs_message(resource, input)
317
+ else
318
+ { "error" => "Unknown resource type" }
319
+ end
320
+ end
321
+
322
+ private
323
+
324
+ def execute_local_method(resource, input)
325
+ method_name = resource.sub('method:', '')
326
+ # Your method dispatch logic
327
+ end
328
+ end
329
+
330
+ execution.context[:task_executor] = CustomExecutor.new
331
+ ```
332
+ ### Error Handling
333
+
334
+ #### Catch Blocks
335
+
336
+ ```yaml
337
+ ProcessPayment:
338
+ Type: Task
339
+ Resource: method:process_payment
340
+ Catch:
341
+ - ErrorEquals: ["InsufficientFunds", "CardDeclined"]
342
+ Next: HandlePaymentFailure
343
+ ResultPath: $.payment_error
344
+ - ErrorEquals: ["States.Timeout"]
345
+ Next: HandleTimeout
346
+ - ErrorEquals: ["States.ALL"]
347
+ Next: HandleGenericError
348
+ Next: NextState
349
+ ```
350
+
351
+ ## Testing
352
+
353
+ ### Unit Testing Workflows
354
+ ```ruby
355
+ require 'spec_helper'
356
+
357
+ RSpec.describe 'Order Workflow' do
358
+ let(:processor) { OrderProcessor.new }
359
+ let(:executor) { ->(r, i, c) { processor.send(r.sub('method:', ''), i) } }
360
+
361
+ it 'processes orders successfully' do
362
+ state_machine = StatesLanguageMachine.from_yaml_file('workflows/order_processing.yaml')
363
+ execution = state_machine.start_execution(order_input, "test-execution")
364
+ execution.context[:task_executor] = executor
365
+ execution.run_all
366
+
367
+ expect(execution.status).to eq('succeeded')
368
+ expect(execution.output['confirmation_result']['confirmation_sent']).to be true
369
+ end
370
+ end
371
+ ```
372
+ ### Testing Error Scenarios
373
+
374
+ ```ruby
375
+ it 'handles payment failures gracefully' do
376
+ # Mock payment failure
377
+ allow(processor).to receive(:process_payment).and_raise('Payment declined')
378
+
379
+ execution.run_all
380
+
381
+ expect(execution.status).to eq('succeeded') # Because catch handled it
382
+ expect(execution.output['payment_failure_handled']).to be true
383
+ end
384
+ ```
385
+
386
+ ## Configuration
387
+ ### Execution Context
388
+ ```ruby
389
+ execution.context = {
390
+ task_executor: your_executor,
391
+ method_receiver: your_object, # For method: resources
392
+ logger: Logger.new($stdout), # For execution logging
393
+ metrics: your_metrics_client # For monitoring
394
+ }
395
+ ```
396
+
397
+ ### Timeout configuration
398
+ ```yaml
399
+ LongRunningTask:
400
+ Type: Task
401
+ Resource: method:long_running_process
402
+ TimeoutSeconds: 3600 # 1 hour timeout
403
+ HeartbeatSeconds: 300 # 5 minute heartbeat
404
+ Next: NextState
405
+ ```
406
+
407
+ ## Examples
408
+ ### Check the examples/ directory for complete working examples:
409
+
410
+ - exammples/ - Complex order processing workflow
411
+ - examples/test_complex_workflow.rb
412
+ ```bash
413
+ ๐Ÿš€ Starting Complex Workflow Test
414
+ This tests Pass, Task, Choice, Succeed, and Fail states with local methods
415
+
416
+ ๐Ÿ“„ Generated workflow file: complex_workflow.yaml
417
+
418
+ ============================================================
419
+ ๐Ÿงช Testing: Premium Order
420
+ ============================================================
421
+ ๐Ÿ“ž Executing: determine_order_type
422
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
423
+ StringEquals
424
+ true
425
+ ๐Ÿ“ž Executing: process_premium_order
426
+ ๐Ÿ“ž Executing: process_payment
427
+ ๐Ÿ“ž Executing: update_inventory
428
+ โœ… Workflow completed successfully!
429
+ ๐Ÿ“Š Final Status: failed
430
+ ๐Ÿ›ฃ๏ธ Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment
431
+ โฑ๏ธ Execution Time: 0.0008 seconds
432
+ ๐Ÿ“ฆ Output Keys: order, $, order_type_result, premium_result, payment_result
433
+ - order_type_result: order_type,reason
434
+ - premium_result: premium_processed,order_id,vip_handling,dedicated_support,processing_tier
435
+ - payment_result: status,payment_id,amount_charged,currency,processed_at
436
+
437
+
438
+ ============================================================
439
+ ๐Ÿงช Testing: Bulk Order (Available)
440
+ ============================================================
441
+ ๐Ÿ“ž Executing: determine_order_type
442
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
443
+ StringEquals
444
+ true
445
+ ๐Ÿ“ž Executing: process_premium_order
446
+ ๐Ÿ“ž Executing: process_payment
447
+ ๐Ÿ“ž Executing: update_inventory
448
+ โœ… Workflow completed successfully!
449
+ ๐Ÿ“Š Final Status: failed
450
+ ๐Ÿ›ฃ๏ธ Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment
451
+ โฑ๏ธ Execution Time: 0.0003 seconds
452
+ ๐Ÿ“ฆ Output Keys: order, $, order_type_result, premium_result, payment_result
453
+ - order_type_result: order_type,reason
454
+ - premium_result: premium_processed,order_id,vip_handling,dedicated_support,processing_tier
455
+ - payment_result: status,payment_id,amount_charged,currency,processed_at
456
+
457
+
458
+ ============================================================
459
+ ๐Ÿงช Testing: Digital Order
460
+ ============================================================
461
+ ๐Ÿ“ž Executing: determine_order_type
462
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
463
+ StringEquals
464
+ false
465
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "bulk", "Next" => "CheckBulkInventory"}
466
+ StringEquals
467
+ false
468
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "international", "Next" => "ProcessInternationalOrder"}
469
+ StringEquals
470
+ true
471
+ ๐Ÿ“ž Executing: process_international_order
472
+ ๐Ÿ“ž Executing: process_payment
473
+ ๐Ÿ“ž Executing: update_inventory
474
+ โœ… Workflow completed successfully!
475
+ ๐Ÿ“Š Final Status: failed
476
+ ๐Ÿ›ฃ๏ธ Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessInternationalOrder โ†’ ProcessPayment
477
+ โฑ๏ธ Execution Time: 0.0003 seconds
478
+ ๐Ÿ“ฆ Output Keys: order, $, order_type_result, international_result, payment_result
479
+ - order_type_result: order_type,reason
480
+ - international_result: international_processed,order_id,destination_country,export_documentation,customs_declaration
481
+ - payment_result: status,payment_id,amount_charged,currency,processed_at
482
+
483
+
484
+ ============================================================
485
+ ๐Ÿงช Testing: Standard Order
486
+ ============================================================
487
+ ๐Ÿ“ž Executing: determine_order_type
488
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
489
+ StringEquals
490
+ false
491
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "bulk", "Next" => "CheckBulkInventory"}
492
+ StringEquals
493
+ false
494
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "international", "Next" => "ProcessInternationalOrder"}
495
+ StringEquals
496
+ false
497
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "digital", "Next" => "ProcessDigitalOrder"}
498
+ StringEquals
499
+ false
500
+ ๐Ÿ“ž Executing: process_standard_order
501
+ ๐Ÿ“ž Executing: process_payment
502
+ ๐Ÿ“ž Executing: update_inventory
503
+ โœ… Workflow completed successfully!
504
+ ๐Ÿ“Š Final Status: failed
505
+ ๐Ÿ›ฃ๏ธ Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessStandardOrder โ†’ ProcessPayment
506
+ โฑ๏ธ Execution Time: 0.0003 seconds
507
+ ๐Ÿ“ฆ Output Keys: order, $, order_type_result, standard_result, payment_result
508
+ - order_type_result: order_type,reason
509
+ - standard_result: standard_processed,order_id,processing_tier
510
+ - payment_result: status,payment_id,amount_charged,currency,processed_at
511
+
512
+
513
+ ============================================================
514
+ ๐Ÿงช Testing: Payment Failure Order
515
+ ============================================================
516
+ ๐Ÿ“ž Executing: determine_order_type
517
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
518
+ StringEquals
519
+ true
520
+ ๐Ÿ“ž Executing: process_premium_order
521
+ ๐Ÿ“ž Executing: process_payment
522
+ ๐Ÿ“ž Executing: update_inventory
523
+ {"Variable" => "$.order.shipping.required", "BooleanEquals" => false, "Next" => "SendDigitalDelivery"}
524
+ BooleanEquals
525
+ false
526
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ScheduleExpressShipping"}
527
+ StringEquals
528
+ true
529
+ ๐Ÿ“ž Executing: schedule_express_shipping
530
+ ๐Ÿ“ž Executing: send_order_confirmation
531
+ โœ… Workflow completed successfully!
532
+ ๐Ÿ“Š Final Status: succeeded
533
+ ๐Ÿ›ฃ๏ธ Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment โ†’ HandleShipping โ†’ ScheduleExpressShipping โ†’ SendOrderConfirmation
534
+ โฑ๏ธ Execution Time: 0.0005 seconds
535
+ ๐Ÿ“ฆ Output Keys: order, $, order_type_result, premium_result, payment_result, inventory_error, shipping_result, confirmation_result
536
+ - order_type_result: order_type,reason
537
+ - premium_result: premium_processed,order_id,vip_handling,dedicated_support,processing_tier
538
+ - payment_result: status,payment_id,amount_charged,currency,processed_at
539
+ - shipping_result: shipping_scheduled,order_id,method,estimated_days,tracking_number,priority
540
+ - confirmation_result: confirmation_sent,order_id,customer_id,sent_via,confirmation_id
541
+
542
+ ๐ŸŽ‰ All tests completed!
543
+ ```
544
+ - examples/test_parallel_complex_workflow.rb
545
+ ```bash
546
+ ๐Ÿš€ Starting Enhanced Complex Workflow Test
547
+ Testing ALL state types: Pass, Task, Choice, Parallel, Succeed, Fail
548
+ With retry mechanisms, error handling, and parallel processing
549
+
550
+ ๐Ÿ“„ Generated enhanced workflow file: complex_workflow_with_parallel.yaml
551
+
552
+ ======================================================================
553
+ ๐Ÿงช ๐Ÿ† Premium Order with Parallel Processing
554
+ ======================================================================
555
+ ๐Ÿ“ž Executing: determine_order_type
556
+ [determine_order_type] Analyzing order: ORD-PREM-001 - Total: $750.0, Items: 2, Quantity: 2
557
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
558
+ StringEquals
559
+ true
560
+ ๐Ÿ“ž Executing: process_premium_order
561
+ [process_premium_order] VIP processing for: ORD-PREM-001
562
+ ๐Ÿ“ž Executing: process_payment
563
+ [process_payment] Processing $0.0 via
564
+ {"Variable" => "$.payment_result.status", "StringEquals" => "completed", "Next" => "ParallelPostPayment"}
565
+ StringEquals
566
+ true
567
+ ๐Ÿ“ž Executing: update_inventory
568
+ [update_inventory] Updating inventory for:
569
+ ๐Ÿ“ž Executing: send_customer_notifications
570
+ [send_customer_notifications] Sending notifications: ORD-PREM-001
571
+ ๐Ÿ“ž Executing: generate_analytics
572
+ [generate_analytics] Generating analytics: ORD-PREM-001
573
+ ๐Ÿ“ž Executing: process_loyalty_points
574
+ [process_loyalty_points] Processing loyalty: CUST-PREM-001
575
+ โœ… Workflow completed successfully!
576
+ ๐Ÿ“Š Final Status: failed
577
+ ๐Ÿ›ฃ๏ธ Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment โ†’ VerifyPaymentSuccess
578
+ โฑ๏ธ Execution Time: 0.0066 seconds
579
+ ๐Ÿ“ˆ States Visited: 6
580
+ ๐Ÿ“ฆ Final Output Summary:
581
+ - order: id, total, customer_id, items, quantity, premium_customer, payment_method, shipping
582
+ - $: validation_metadata
583
+ - order_type_result: order_type, reason
584
+ - premium_result: premium_processed, order_id, vip_handling, dedicated_support, processing_tier, priority_level
585
+ - payment_result: status, payment_id, amount_charged, currency, processed_at, attempts
586
+
587
+
588
+ ======================================================================
589
+ ๐Ÿงช ๐Ÿ“ฆ Bulk Order (Testing Retry)
590
+ ======================================================================
591
+ ๐Ÿ“ž Executing: determine_order_type
592
+ [determine_order_type] Analyzing order: ORD-BULK-001 - Total: $1800.0, Items: 1, Quantity: 25
593
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
594
+ StringEquals
595
+ true
596
+ ๐Ÿ“ž Executing: process_premium_order
597
+ [process_premium_order] VIP processing for: ORD-BULK-001
598
+ ๐Ÿ“ž Executing: process_payment
599
+ [process_payment] Processing $0.0 via
600
+ {"Variable" => "$.payment_result.status", "StringEquals" => "completed", "Next" => "ParallelPostPayment"}
601
+ StringEquals
602
+ true
603
+ ๐Ÿ“ž Executing: update_inventory
604
+ [update_inventory] Updating inventory for:
605
+ ๐Ÿ“ž Executing: send_customer_notifications
606
+ [send_customer_notifications] Sending notifications: ORD-BULK-001
607
+ ๐Ÿ“ž Executing: generate_analytics
608
+ [generate_analytics] Generating analytics: ORD-BULK-001
609
+ ๐Ÿ“ž Executing: process_loyalty_points
610
+ [process_loyalty_points] Processing loyalty: CUST-BULK-001
611
+ โœ… Workflow completed successfully!
612
+ ๐Ÿ“Š Final Status: failed
613
+ ๐Ÿ›ฃ๏ธ Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment โ†’ VerifyPaymentSuccess
614
+ โฑ๏ธ Execution Time: 0.0033 seconds
615
+ ๐Ÿ“ˆ States Visited: 6
616
+ ๐Ÿ“ฆ Final Output Summary:
617
+ - order: id, total, customer_id, items, quantity, payment_method, shipping
618
+ - $: validation_metadata
619
+ - order_type_result: order_type, reason
620
+ - premium_result: premium_processed, order_id, vip_handling, dedicated_support, processing_tier, priority_level
621
+ - payment_result: status, payment_id, amount_charged, currency, processed_at, attempts
622
+
623
+
624
+ ======================================================================
625
+ ๐Ÿงช ๐Ÿ’ป Digital Order (No Shipping)
626
+ ======================================================================
627
+ ๐Ÿ“ž Executing: determine_order_type
628
+ [determine_order_type] Analyzing order: ORD-DIG-001 - Total: $49.99, Items: 1, Quantity: 1
629
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
630
+ StringEquals
631
+ false
632
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "bulk", "Next" => "CheckBulkInventory"}
633
+ StringEquals
634
+ false
635
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "international", "Next" => "ProcessInternationalOrder"}
636
+ StringEquals
637
+ true
638
+ ๐Ÿ“ž Executing: process_international_order
639
+ [process_international_order] International processing for: ORD-DIG-001 to
640
+ ๐Ÿ“ž Executing: process_payment
641
+ [process_payment] Processing $0.0 via
642
+ {"Variable" => "$.payment_result.status", "StringEquals" => "completed", "Next" => "ParallelPostPayment"}
643
+ StringEquals
644
+ true
645
+ ๐Ÿ“ž Executing: update_inventory
646
+ [update_inventory] Updating inventory for:
647
+ ๐Ÿ“ž Executing: send_customer_notifications
648
+ [send_customer_notifications] Sending notifications: ORD-DIG-001
649
+ ๐Ÿ“ž Executing: generate_analytics
650
+ [generate_analytics] Generating analytics: ORD-DIG-001
651
+ ๐Ÿ“ž Executing: process_loyalty_points
652
+ [process_loyalty_points] Processing loyalty: CUST-DIG-001
653
+ โœ… Workflow completed successfully!
654
+ ๐Ÿ“Š Final Status: failed
655
+ ๐Ÿ›ฃ๏ธ Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessInternationalOrder โ†’ ProcessPayment โ†’ VerifyPaymentSuccess
656
+ โฑ๏ธ Execution Time: 0.003 seconds
657
+ ๐Ÿ“ˆ States Visited: 6
658
+ ๐Ÿ“ฆ Final Output Summary:
659
+ - order: id, total, customer_id, items, quantity, payment_method, shipping, digital_product, customer_email
660
+ - $: validation_metadata
661
+ - order_type_result: order_type, reason
662
+ - international_result: international_processed, order_id, destination_country, export_documentation, customs_declaration, requires_export_license
663
+ - payment_result: status, payment_id, amount_charged, currency, processed_at, attempts
664
+
665
+
666
+ ======================================================================
667
+ ๐Ÿงช ๐ŸŒ International Order
668
+ ======================================================================
669
+ ๐Ÿ“ž Executing: determine_order_type
670
+ [determine_order_type] Analyzing order: ORD-INT-001 - Total: $299.99, Items: 1, Quantity: 1
671
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
672
+ StringEquals
673
+ false
674
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "bulk", "Next" => "CheckBulkInventory"}
675
+ StringEquals
676
+ false
677
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "international", "Next" => "ProcessInternationalOrder"}
678
+ StringEquals
679
+ true
680
+ ๐Ÿ“ž Executing: process_international_order
681
+ [process_international_order] International processing for: ORD-INT-001 to
682
+ ๐Ÿ“ž Executing: process_payment
683
+ [process_payment] Processing $0.0 via
684
+ {"Variable" => "$.payment_result.status", "StringEquals" => "completed", "Next" => "ParallelPostPayment"}
685
+ StringEquals
686
+ true
687
+ ๐Ÿ“ž Executing: update_inventory
688
+ [update_inventory] Updating inventory for:
689
+ ๐Ÿ“ž Executing: send_customer_notifications
690
+ [send_customer_notifications] Sending notifications: ORD-INT-001
691
+ ๐Ÿ“ž Executing: generate_analytics
692
+ [generate_analytics] Generating analytics: ORD-INT-001
693
+ ๐Ÿ“ž Executing: process_loyalty_points
694
+ [process_loyalty_points] Processing loyalty: CUST-INT-001
695
+ โœ… Workflow completed successfully!
696
+ ๐Ÿ“Š Final Status: failed
697
+ ๐Ÿ›ฃ๏ธ Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessInternationalOrder โ†’ ProcessPayment โ†’ VerifyPaymentSuccess
698
+ โฑ๏ธ Execution Time: 0.0031 seconds
699
+ ๐Ÿ“ˆ States Visited: 6
700
+ ๐Ÿ“ฆ Final Output Summary:
701
+ - order: id, total, customer_id, items, quantity, payment_method, shipping
702
+ - $: validation_metadata
703
+ - order_type_result: order_type, reason
704
+ - international_result: international_processed, order_id, destination_country, export_documentation, customs_declaration, requires_export_license
705
+ - payment_result: status, payment_id, amount_charged, currency, processed_at, attempts
706
+
707
+
708
+ ======================================================================
709
+ ๐Ÿงช ๐Ÿ’ธ Payment Failure Scenario
710
+ ======================================================================
711
+ ๐Ÿ“ž Executing: determine_order_type
712
+ [determine_order_type] Analyzing order: ORD-FAIL-001 - Total: $2500.0, Items: 1, Quantity: 1
713
+ {"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
714
+ StringEquals
715
+ true
716
+ ๐Ÿ“ž Executing: process_premium_order
717
+ [process_premium_order] VIP processing for: ORD-FAIL-001
718
+ ๐Ÿ“ž Executing: process_payment
719
+ [process_payment] Processing $0.0 via
720
+ {"Variable" => "$.payment_result.status", "StringEquals" => "completed", "Next" => "ParallelPostPayment"}
721
+ StringEquals
722
+ true
723
+ ๐Ÿ“ž Executing: update_inventory
724
+ [update_inventory] Updating inventory for:
725
+ ๐Ÿ“ž Executing: send_customer_notifications
726
+ [send_customer_notifications] Sending notifications: ORD-FAIL-001
727
+ ๐Ÿ“ž Executing: generate_analytics
728
+ [generate_analytics] Generating analytics: ORD-FAIL-001
729
+ ๐Ÿ“ž Executing: process_loyalty_points
730
+ [process_loyalty_points] Processing loyalty: CUST-FAIL-001
731
+ โœ… Workflow completed successfully!
732
+ ๐Ÿ“Š Final Status: failed
733
+ ๐Ÿ›ฃ๏ธ Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment โ†’ VerifyPaymentSuccess
734
+ โฑ๏ธ Execution Time: 0.0028 seconds
735
+ ๐Ÿ“ˆ States Visited: 6
736
+ ๐Ÿ“ฆ Final Output Summary:
737
+ - order: id, total, customer_id, items, quantity, payment_method, shipping
738
+ - $: validation_metadata
739
+ - order_type_result: order_type, reason
740
+ - premium_result: premium_processed, order_id, vip_handling, dedicated_support, processing_tier, priority_level
741
+ - payment_result: status, payment_id, amount_charged, currency, processed_at, attempts
742
+
743
+ ๐ŸŽ‰ All tests completed!
744
+
745
+ ๐Ÿ“‹ State Types Demonstrated:
746
+ โœ… Pass - Data transformation
747
+ โœ… Task - Business logic execution
748
+ โœ… Choice - Conditional routing
749
+ โœ… Parallel - Concurrent branch execution
750
+ โœ… Succeed - Successful termination
751
+ โœ… Fail - Error termination
752
+ โœ… Retry - Automatic retry mechanisms
753
+ โœ… Catch - Error handling blocks
754
+ ```
755
+
756
+
757
+ ## License
758
+ The gem is available as open source under the terms of the MIT License.
759
+
760
+ ## Acknowledgments
761
+ Inspired by AWS Step Functions state language
762
+
763
+ Built for Ruby developers who need workflow orchestration
764
+
765
+ Designed for both simple and complex business processes
766
+
767
+ ## Author
768
+ - Hussain Pithawala (https://www.linkedin.com/in/hussainpithawala)