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.
@@ -0,0 +1,983 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'yaml'
5
+ require 'securerandom'
6
+
7
+ # Enhanced ComplexOrderProcessor with parallel processing capabilities
8
+ class ComplexOrderProcessor
9
+ # Order Classification
10
+ def determine_order_type(input)
11
+ order = input['order'] || {}
12
+
13
+ total = order['total'].to_f
14
+ items = order['items'] || []
15
+ quantity = order['quantity'].to_i
16
+
17
+ puts " [determine_order_type] Analyzing order: #{order['id']} - Total: $#{total}, Items: #{items.size}, Quantity: #{quantity}"
18
+
19
+ # Business logic for order classification
20
+ if total > 500 || order['premium_customer']
21
+ { "order_type" => "premium", "reason" => "high_value_or_premium_customer" }
22
+ elsif quantity > 10 || total > 1000
23
+ { "order_type" => "bulk", "reason" => "large_quantity" }
24
+ elsif order['shipping'] && order['shipping']['country'] != 'US'
25
+ { "order_type" => "international", "reason" => "international_shipping" }
26
+ elsif order['digital_product']
27
+ { "order_type" => "digital", "reason" => "digital_product" }
28
+ else
29
+ { "order_type" => "standard", "reason" => "regular_order" }
30
+ end
31
+ end
32
+
33
+ # Premium Order Processing
34
+ def process_premium_order(input)
35
+ order = input['order']
36
+ puts " [process_premium_order] VIP processing for: #{order['id']}"
37
+
38
+ {
39
+ "premium_processed" => true,
40
+ "order_id" => order['id'],
41
+ "vip_handling" => true,
42
+ "dedicated_support" => true,
43
+ "processing_tier" => "premium",
44
+ "priority_level" => 1
45
+ }
46
+ end
47
+
48
+ # Bulk Order Processing
49
+ def check_bulk_inventory(input)
50
+ order = input['order']
51
+ required_quantity = input['required_quantity']
52
+
53
+ puts " [check_bulk_inventory] Checking bulk inventory for: #{order['id']}"
54
+
55
+ # Simulate inventory check with occasional delays
56
+ sleep(0.05) if rand(0..1) == 0 # Simulate API call
57
+
58
+ available = rand(0..1) == 1
59
+ {
60
+ "available" => available,
61
+ "checked_at" => Time.now.to_i,
62
+ "required_quantity" => required_quantity,
63
+ "available_quantity" => available ? required_quantity : 0,
64
+ "warehouse" => "main_warehouse"
65
+ }
66
+ end
67
+
68
+ def process_bulk_order(input)
69
+ order = input['order']
70
+ puts " [process_bulk_order] Processing bulk order: #{order['id']}"
71
+
72
+ {
73
+ "bulk_processed" => true,
74
+ "order_id" => order['id'],
75
+ "volume_discount_applied" => true,
76
+ "special_handling" => true,
77
+ "bulk_tier" => "large"
78
+ }
79
+ end
80
+
81
+ # International Order Processing
82
+ def process_international_order(input)
83
+ order = input['order']
84
+ country = input['destination_country']
85
+
86
+ puts " [process_international_order] International processing for: #{order['id']} to #{country}"
87
+
88
+ {
89
+ "international_processed" => true,
90
+ "order_id" => order['id'],
91
+ "destination_country" => country,
92
+ "export_documentation" => "required",
93
+ "customs_declaration" => "needed",
94
+ "requires_export_license" => country == 'IR' # Example restriction
95
+ }
96
+ end
97
+
98
+ def calculate_customs_duty(input)
99
+ order_value = input['order_value'].to_f
100
+ country = input['country']
101
+
102
+ puts " [calculate_customs_duty] Calculating duty for $#{order_value} to #{country}"
103
+
104
+ # Simple customs calculation
105
+ duty_rate = case country
106
+ when 'CA', 'MX' then 0.05
107
+ when 'EU' then 0.15
108
+ when 'UK' then 0.12
109
+ else 0.10
110
+ end
111
+
112
+ duty_amount = order_value * duty_rate
113
+
114
+ {
115
+ "duty_calculated" => true,
116
+ "duty_rate" => duty_rate,
117
+ "duty_amount" => duty_amount,
118
+ "total_with_duty" => order_value + duty_amount,
119
+ "currency" => "USD",
120
+ "calculation_method" => "standard"
121
+ }
122
+ end
123
+
124
+ # Digital Order Processing
125
+ def process_digital_order(input)
126
+ order = input['order']
127
+ puts " [process_digital_order] Digital order processing: #{order['id']}"
128
+
129
+ {
130
+ "digital_processed" => true,
131
+ "order_id" => order['id'],
132
+ "product_type" => order['digital_product']['type'],
133
+ "instant_delivery" => true,
134
+ "digital_rights" => "granted"
135
+ }
136
+ end
137
+
138
+ def generate_digital_access(input)
139
+ puts " [generate_digital_access] Generating access for: #{input['order_id']}"
140
+
141
+ {
142
+ "access_generated" => true,
143
+ "order_id" => input['order_id'],
144
+ "access_codes" => ["CODE-#{SecureRandom.hex(8)}"],
145
+ "download_links" => ["https://download.example.com/#{SecureRandom.hex(4)}"],
146
+ "license_key" => "LIC-#{SecureRandom.hex(12)}",
147
+ "valid_until" => (Time.now + 365 * 24 * 60 * 60).to_i # 1 year
148
+ }
149
+ end
150
+
151
+ # Standard Order Processing
152
+ def process_standard_order(input)
153
+ order = input['order']
154
+ puts " [process_standard_order] Standard processing: #{order['id']}"
155
+
156
+ {
157
+ "standard_processed" => true,
158
+ "order_id" => order['id'],
159
+ "processing_tier" => "standard",
160
+ "service_level" => "normal"
161
+ }
162
+ end
163
+
164
+ # Payment Processing with retry simulation
165
+ def process_payment(input)
166
+ amount = input['amount'].to_f
167
+ payment_method = input['payment_method']
168
+
169
+ puts " [process_payment] Processing $#{amount} via #{payment_method}"
170
+
171
+ # Simulate payment processing with retry scenarios
172
+ @payment_attempts ||= {}
173
+ order_id = input['order_id']
174
+ @payment_attempts[order_id] ||= 0
175
+ @payment_attempts[order_id] += 1
176
+
177
+ # Fail first attempt for certain conditions to test retry
178
+ if @payment_attempts[order_id] == 1 && amount > 1500
179
+ raise "PaymentGatewayTimeout - Gateway busy, please retry"
180
+ end
181
+
182
+ success = amount < 2000 && payment_method != 'expired_card'
183
+
184
+ if success
185
+ {
186
+ "status" => "completed",
187
+ "payment_id" => "pay_#{SecureRandom.hex(8)}",
188
+ "amount_charged" => amount,
189
+ "currency" => input['currency'],
190
+ "processed_at" => Time.now.to_i,
191
+ "attempts" => @payment_attempts[order_id]
192
+ }
193
+ else
194
+ raise "Payment declined: #{payment_method} cannot process $#{amount}"
195
+ end
196
+ end
197
+
198
+ def wait_for_payment_confirmation(input)
199
+ payment_id = input['payment_id']
200
+
201
+ puts " [wait_for_payment_confirmation] Waiting for confirmation: #{payment_id}"
202
+
203
+ # Simulate waiting for confirmation
204
+ sleep(0.1)
205
+
206
+ {
207
+ "confirmed" => true,
208
+ "payment_id" => payment_id,
209
+ "confirmation_code" => "CONF-#{SecureRandom.hex(6)}",
210
+ "confirmed_at" => Time.now.to_i,
211
+ "confirmation_method" => "3ds_secure"
212
+ }
213
+ end
214
+
215
+ def finalize_payment(input)
216
+ puts " [finalize_payment] Finalizing: #{input['payment_id']}"
217
+
218
+ {
219
+ "finalized" => true,
220
+ "payment_id" => input['payment_id'],
221
+ "status" => "completed",
222
+ "finalized_at" => Time.now.to_i,
223
+ "settlement_initiated" => true
224
+ }
225
+ end
226
+
227
+ # Inventory Management
228
+ def update_inventory(input)
229
+ order_id = input['order_id']
230
+ items = input['items']
231
+
232
+ puts " [update_inventory] Updating inventory for: #{order_id}"
233
+
234
+ # Simulate inventory update with occasional stock issues
235
+ out_of_stock = rand(0..9) == 0 # 10% chance of out of stock
236
+
237
+ if out_of_stock
238
+ raise "OutOfStock - Item unavailable for order #{order_id}"
239
+ else
240
+ {
241
+ "inventory_updated" => true,
242
+ "order_id" => order_id,
243
+ "items_processed" => items.size,
244
+ "updated_at" => Time.now.to_i,
245
+ "inventory_system" => "warehouse_db_v2"
246
+ }
247
+ end
248
+ end
249
+
250
+ # Shipping Methods
251
+ def schedule_express_shipping(input)
252
+ order = input['order']
253
+ puts " [schedule_express_shipping] Express shipping for: #{order['id']}"
254
+
255
+ {
256
+ "shipping_scheduled" => true,
257
+ "order_id" => order['id'],
258
+ "method" => "express",
259
+ "estimated_days" => 1,
260
+ "tracking_number" => "EXP#{SecureRandom.hex(6).upcase}",
261
+ "priority" => "high",
262
+ "carrier" => "fedex_priority"
263
+ }
264
+ end
265
+
266
+ def schedule_standard_shipping(input)
267
+ order = input['order']
268
+ puts " [schedule_standard_shipping] Standard shipping for: #{order['id']}"
269
+
270
+ {
271
+ "shipping_scheduled" => true,
272
+ "order_id" => order['id'],
273
+ "method" => "standard",
274
+ "estimated_days" => 3,
275
+ "tracking_number" => "STD#{SecureRandom.hex(6).upcase}",
276
+ "carrier" => "ups_ground"
277
+ }
278
+ end
279
+
280
+ def schedule_economy_shipping(input)
281
+ order = input['order']
282
+ puts " [schedule_economy_shipping] Economy shipping for: #{order['id']}"
283
+
284
+ {
285
+ "shipping_scheduled" => true,
286
+ "order_id" => order['id'],
287
+ "method" => "economy",
288
+ "estimated_days" => 7,
289
+ "tracking_number" => "ECO#{SecureRandom.hex(6).upcase}",
290
+ "carrier" => "usps_parcel"
291
+ }
292
+ end
293
+
294
+ # Digital Delivery
295
+ def send_digital_delivery(input)
296
+ order = input['order']
297
+ puts " [send_digital_delivery] Sending digital delivery: #{order['id']}"
298
+
299
+ {
300
+ "digital_delivered" => true,
301
+ "order_id" => order['id'],
302
+ "customer_email" => input['customer_email'],
303
+ "delivery_method" => "email",
304
+ "sent_at" => Time.now.to_i,
305
+ "delivery_status" => "sent"
306
+ }
307
+ end
308
+
309
+ # Parallel Processing Methods
310
+ def send_customer_notifications(input)
311
+ order = input['order']
312
+ puts " [send_customer_notifications] Sending notifications: #{order['id']}"
313
+
314
+ {
315
+ "notifications_sent" => true,
316
+ "order_id" => order['id'],
317
+ "email_sent" => true,
318
+ "sms_sent" => true,
319
+ "push_notification_sent" => true,
320
+ "notification_timestamp" => Time.now.to_i
321
+ }
322
+ end
323
+
324
+ def update_customer_profile(input)
325
+ order = input['order']
326
+ puts " [update_customer_profile] Updating profile: #{order['customer_id']}"
327
+
328
+ {
329
+ "profile_updated" => true,
330
+ "customer_id" => order['customer_id'],
331
+ "order_count_incremented" => true,
332
+ "loyalty_points_added" => (order['total'].to_i / 10),
333
+ "last_order_date" => Time.now.to_i
334
+ }
335
+ end
336
+
337
+ def generate_analytics(input)
338
+ order = input['order']
339
+ puts " [generate_analytics] Generating analytics: #{order['id']}"
340
+
341
+ {
342
+ "analytics_generated" => true,
343
+ "order_id" => order['id'],
344
+ "revenue_tracked" => order['total'],
345
+ "customer_segment" => order['total'] > 100 ? "high_value" : "standard",
346
+ "analytics_timestamp" => Time.now.to_i
347
+ }
348
+ end
349
+
350
+ def process_loyalty_points(input)
351
+ order = input['order']
352
+ puts " [process_loyalty_points] Processing loyalty: #{order['customer_id']}"
353
+
354
+ points = (order['total'].to_i / 5).to_i # 1 point per $5
355
+
356
+ {
357
+ "loyalty_processed" => true,
358
+ "customer_id" => order['customer_id'],
359
+ "points_earned" => points,
360
+ "total_points" => rand(100..1000) + points,
361
+ "tier_checked" => true
362
+ }
363
+ end
364
+
365
+ # Notifications
366
+ def send_order_confirmation(input)
367
+ order = input['order']
368
+ puts " [send_order_confirmation] Sending confirmation: #{order['id']}"
369
+
370
+ {
371
+ "confirmation_sent" => true,
372
+ "order_id" => order['id'],
373
+ "customer_id" => input['customer'],
374
+ "sent_via" => ["email", "sms"],
375
+ "confirmation_id" => "CONF-#{SecureRandom.hex(6)}",
376
+ "template_used" => "order_confirmation_v2"
377
+ }
378
+ end
379
+
380
+ # Error Handling Methods
381
+ def handle_classification_error(input)
382
+ puts " [handle_classification_error] Recovering from classification error"
383
+
384
+ {
385
+ "classification_recovered" => true,
386
+ "order_id" => input['order']['id'],
387
+ "fallback_strategy" => "standard_processing",
388
+ "recovered_at" => Time.now.to_i,
389
+ "recovery_method" => "fallback_to_standard"
390
+ }
391
+ end
392
+
393
+ def handle_payment_failure(input)
394
+ order = input['order']
395
+ puts " [handle_payment_failure] Handling payment failure: #{order['id']}"
396
+
397
+ {
398
+ "payment_failure_handled" => true,
399
+ "order_id" => order['id'],
400
+ "attempt" => input['payment_attempt'],
401
+ "next_action" => "notify_customer",
402
+ "handled_at" => Time.now.to_i,
403
+ "escalation_level" => "customer_support"
404
+ }
405
+ end
406
+
407
+ def notify_payment_failure(input)
408
+ order = input['order']
409
+ puts " [notify_payment_failure] Notifying customer: #{order['id']}"
410
+
411
+ {
412
+ "payment_failure_notified" => true,
413
+ "order_id" => order['id'],
414
+ "customer_notified" => true,
415
+ "notification_method" => "email",
416
+ "notified_at" => Time.now.to_i,
417
+ "notification_template" => "payment_failed_v1"
418
+ }
419
+ end
420
+
421
+ def handle_out_of_stock(input)
422
+ order = input['order']
423
+ puts " [handle_out_of_stock] Handling out of stock: #{order['id']}"
424
+
425
+ {
426
+ "out_of_stock_handled" => true,
427
+ "order_id" => order['id'],
428
+ "action" => "notify_customer_and_restock",
429
+ "handled_at" => Time.now.to_i,
430
+ "restock_eta" => Time.now + 7 * 24 * 60 * 60 # 7 days
431
+ }
432
+ end
433
+
434
+ def notify_out_of_stock(input)
435
+ order = input['order']
436
+ puts " [notify_out_of_stock] Notifying out of stock: #{order['id']}"
437
+
438
+ {
439
+ "out_of_stock_notified" => true,
440
+ "order_id" => order['id'],
441
+ "customer_notified" => true,
442
+ "notification_method" => "email",
443
+ "notified_at" => Time.now.to_i,
444
+ "alternative_suggested" => true
445
+ }
446
+ end
447
+
448
+ def handle_bulk_unavailable(input)
449
+ order = input['order']
450
+ puts " [handle_bulk_unavailable] Handling bulk unavailable: #{order['id']}"
451
+
452
+ {
453
+ "bulk_unavailable_handled" => true,
454
+ "order_id" => order['id'],
455
+ "action" => "offer_alternative",
456
+ "handled_at" => Time.now.to_i,
457
+ "fallback_to_standard" => true
458
+ }
459
+ end
460
+ end
461
+
462
+ # Simple executor that routes to ComplexOrderProcessor methods
463
+ class LocalMethodExecutor
464
+ def initialize
465
+ @processor = ComplexOrderProcessor.new
466
+ end
467
+
468
+ def call(resource, input, credentials = nil)
469
+ method_name = resource.sub('method:', '')
470
+
471
+ unless @processor.respond_to?(method_name)
472
+ raise "Method not found: #{method_name}"
473
+ end
474
+
475
+ puts " ๐Ÿ“ž Executing: #{method_name}"
476
+ @processor.send(method_name, input)
477
+ end
478
+ end
479
+
480
+ # Enhanced workflow tester with Parallel states
481
+ class WorkflowTester
482
+ def initialize
483
+ @executor = LocalMethodExecutor.new
484
+ @workflow_file = 'complex_workflow_with_parallel.yaml'
485
+ generate_workflow_file
486
+ end
487
+
488
+ def generate_workflow_file
489
+ workflow_yaml = <<~YAML
490
+ Comment: Complex E-commerce Workflow with Parallel Processing
491
+ StartAt: ValidateInput
492
+ States:
493
+ # PASS State - Initial data transformation
494
+ ValidateInput:
495
+ Type: Pass
496
+ Parameters:
497
+ order_id.$: $.order.id
498
+ customer_id.$: $.order.customer_id
499
+ total_amount.$: $.order.total
500
+ item_count.$: $.order.items.length
501
+ timestamp: #{Time.now.to_i}
502
+ workflow_version: "2.1.0"
503
+ ResultPath: $.validation_metadata
504
+ Next: CheckOrderType
505
+
506
+ # TASK State - Order classification
507
+ CheckOrderType:
508
+ Type: Task
509
+ Resource: method:determine_order_type
510
+ ResultPath: $.order_type_result
511
+ Next: RouteOrder
512
+ Retry:
513
+ - ErrorEquals: ["States.ALL"]
514
+ IntervalSeconds: 2
515
+ MaxAttempts: 2
516
+ BackoffRate: 1.5
517
+
518
+ # CHOICE State - Route based on order type
519
+ RouteOrder:
520
+ Type: Choice
521
+ Choices:
522
+ - Variable: $.order_type_result.order_type
523
+ StringEquals: "premium"
524
+ Next: ProcessPremiumOrder
525
+ - Variable: $.order_type_result.order_type
526
+ StringEquals: "bulk"
527
+ Next: CheckBulkInventory
528
+ - Variable: $.order_type_result.order_type
529
+ StringEquals: "international"
530
+ Next: ProcessInternationalOrder
531
+ - Variable: $.order_type_result.order_type
532
+ StringEquals: "digital"
533
+ Next: ProcessDigitalOrder
534
+ Default: ProcessStandardOrder
535
+
536
+ # TASK States for different order types
537
+ ProcessPremiumOrder:
538
+ Type: Task
539
+ Resource: method:process_premium_order
540
+ ResultPath: $.premium_result
541
+ Next: ProcessPayment
542
+
543
+ CheckBulkInventory:
544
+ Type: Task
545
+ Resource: method:check_bulk_inventory
546
+ Parameters:
547
+ order.$: $.order
548
+ required_quantity.$: $.order.quantity
549
+ ResultPath: $.bulk_inventory_result
550
+ Next: VerifyBulkAvailability
551
+ Retry:
552
+ - ErrorEquals: ["States.Timeout"]
553
+ IntervalSeconds: 5
554
+ MaxAttempts: 3
555
+ BackoffRate: 2.0
556
+
557
+ VerifyBulkAvailability:
558
+ Type: Choice
559
+ Choices:
560
+ - Variable: $.bulk_inventory_result.available
561
+ BooleanEquals: true
562
+ Next: ProcessBulkOrder
563
+ - Variable: $.bulk_inventory_result.available
564
+ BooleanEquals: false
565
+ Next: HandleBulkUnavailable
566
+ Default: HandleBulkUnavailable
567
+
568
+ ProcessBulkOrder:
569
+ Type: Task
570
+ Resource: method:process_bulk_order
571
+ ResultPath: $.bulk_result
572
+ Next: ProcessPayment
573
+
574
+ HandleBulkUnavailable:
575
+ Type: Task
576
+ Resource: method:handle_bulk_unavailable
577
+ ResultPath: $.bulk_unavailable_result
578
+ Next: ProcessStandardOrder
579
+
580
+ ProcessInternationalOrder:
581
+ Type: Task
582
+ Resource: method:process_international_order
583
+ ResultPath: $.international_result
584
+ Next: ProcessPayment
585
+
586
+ ProcessDigitalOrder:
587
+ Type: Task
588
+ Resource: method:process_digital_order
589
+ ResultPath: $.digital_result
590
+ Next: GenerateDigitalAccess
591
+
592
+ GenerateDigitalAccess:
593
+ Type: Task
594
+ Resource: method:generate_digital_access
595
+ ResultPath: $.digital_access_result
596
+ Next: SendDigitalDelivery
597
+
598
+ ProcessStandardOrder:
599
+ Type: Task
600
+ Resource: method:process_standard_order
601
+ ResultPath: $.standard_result
602
+ Next: ProcessPayment
603
+
604
+ # TASK State - Payment processing with retry
605
+ ProcessPayment:
606
+ Type: Task
607
+ Resource: method:process_payment
608
+ Parameters:
609
+ order_id.$: $.order.id
610
+ amount.$: $.order.total
611
+ currency: "USD"
612
+ payment_method.$: $.order.payment_method
613
+ customer_id.$: $.order.customer_id
614
+ ResultPath: $.payment_result
615
+ Next: VerifyPaymentSuccess
616
+ Retry:
617
+ - ErrorEquals: ["PaymentGatewayTimeout", "States.Timeout"]
618
+ IntervalSeconds: 3
619
+ MaxAttempts: 3
620
+ BackoffRate: 2.0
621
+ Catch:
622
+ - ErrorEquals: ["States.ALL"]
623
+ Next: HandlePaymentFailure
624
+ ResultPath: $.payment_error
625
+
626
+ # CHOICE State - Verify payment outcome
627
+ VerifyPaymentSuccess:
628
+ Type: Choice
629
+ Choices:
630
+ - Variable: $.payment_result.status
631
+ StringEquals: "completed"
632
+ Next: ParallelPostPayment
633
+ - Variable: $.payment_result.status
634
+ StringEquals: "pending"
635
+ Next: WaitForPaymentConfirmation
636
+ Default: HandlePaymentFailure
637
+
638
+ WaitForPaymentConfirmation:
639
+ Type: Task
640
+ Resource: method:wait_for_payment_confirmation
641
+ ResultPath: $.payment_confirmation
642
+ Next: FinalizePayment
643
+
644
+ FinalizePayment:
645
+ Type: Task
646
+ Resource: method:finalize_payment
647
+ ResultPath: $.final_payment_result
648
+ Next: ParallelPostPayment
649
+
650
+ HandlePaymentFailure:
651
+ Type: Task
652
+ Resource: method:handle_payment_failure
653
+ Parameters:
654
+ order.$: $.order
655
+ error.$: $.payment_error
656
+ payment_attempt: 1
657
+ ResultPath: $.payment_failure_result
658
+ Next: NotifyPaymentFailure
659
+
660
+ NotifyPaymentFailure:
661
+ Type: Task
662
+ Resource: method:notify_payment_failure
663
+ ResultPath: $.payment_failure_notification
664
+ End: true
665
+
666
+ # PARALLEL State - Execute multiple tasks concurrently
667
+ ParallelPostPayment:
668
+ Type: Parallel
669
+ Branches:
670
+ - StartAt: UpdateInventoryBranch
671
+ States:
672
+ UpdateInventoryBranch:
673
+ Type: Task
674
+ Resource: method:update_inventory
675
+ Parameters:
676
+ order_id.$: $.order.id
677
+ items.$: $.order.items
678
+ action: "decrement"
679
+ End: true
680
+ ResultPath: $.inventory_result
681
+ Catch:
682
+ - ErrorEquals: ["OutOfStock"]
683
+ Next: HandleOutOfStockBranch
684
+ ResultPath: $.inventory_error
685
+
686
+ HandleOutOfStockBranch:
687
+ Type: Task
688
+ Resource: method:handle_out_of_stock
689
+ ResultPath: $.out_of_stock_result
690
+ End: true
691
+
692
+ - StartAt: CustomerNotificationsBranch
693
+ States:
694
+ CustomerNotificationsBranch:
695
+ Type: Task
696
+ Resource: method:send_customer_notifications
697
+ Parameters:
698
+ order.$: $.order
699
+ End: true
700
+ ResultPath: $.notification_result
701
+
702
+ - StartAt: AnalyticsBranch
703
+ States:
704
+ AnalyticsBranch:
705
+ Type: Task
706
+ Resource: method:generate_analytics
707
+ Parameters:
708
+ order.$: $.order
709
+ End: true
710
+ ResultPath: $.analytics_result
711
+
712
+ - StartAt: LoyaltyBranch
713
+ States:
714
+ LoyaltyBranch:
715
+ Type: Task
716
+ Resource: method:process_loyalty_points
717
+ Parameters:
718
+ order.$: $.order
719
+ End: true
720
+ ResultPath: $.loyalty_result
721
+
722
+ Next: HandleShipping
723
+ Catch:
724
+ - ErrorEquals: ["States.ALL"]
725
+ Next: HandleParallelError
726
+ ResultPath: $.parallel_error
727
+
728
+ HandleParallelError:
729
+ Type: Pass
730
+ Parameters:
731
+ parallel_error_handled: true
732
+ timestamp: #{Time.now.to_i}
733
+ ResultPath: $.parallel_recovery
734
+ Next: HandleShipping
735
+
736
+ # CHOICE State - Shipping decisions
737
+ HandleShipping:
738
+ Type: Choice
739
+ Choices:
740
+ - Variable: $.order.shipping.required
741
+ BooleanEquals: false
742
+ Next: SendDigitalDelivery
743
+ - Variable: $.order_type_result.order_type
744
+ StringEquals: "premium"
745
+ Next: ScheduleExpressShipping
746
+ - Variable: $.order.total
747
+ NumericGreaterThan: 100
748
+ Next: ScheduleStandardShipping
749
+ Default: ScheduleEconomyShipping
750
+
751
+ # TASK States - Shipping methods
752
+ ScheduleExpressShipping:
753
+ Type: Task
754
+ Resource: method:schedule_express_shipping
755
+ ResultPath: $.shipping_result
756
+ Next: FinalConfirmation
757
+
758
+ ScheduleStandardShipping:
759
+ Type: Task
760
+ Resource: method:schedule_standard_shipping
761
+ ResultPath: $.shipping_result
762
+ Next: FinalConfirmation
763
+
764
+ ScheduleEconomyShipping:
765
+ Type: Task
766
+ Resource: method:schedule_economy_shipping
767
+ ResultPath: $.shipping_result
768
+ Next: FinalConfirmation
769
+
770
+ SendDigitalDelivery:
771
+ Type: Task
772
+ Resource: method:send_digital_delivery
773
+ ResultPath: $.digital_delivery_result
774
+ Next: FinalConfirmation
775
+
776
+ # Final confirmation with potential FAIL state
777
+ FinalConfirmation:
778
+ Type: Task
779
+ Resource: method:send_order_confirmation
780
+ ResultPath: $.confirmation_result
781
+ Next: OrderSuccessCheck
782
+
783
+ # CHOICE State - Final success/fail check
784
+ OrderSuccessCheck:
785
+ Type: Choice
786
+ Choices:
787
+ - Variable: $.confirmation_result.confirmation_sent
788
+ BooleanEquals: true
789
+ Next: OrderCompleted
790
+ Default: OrderFailed
791
+
792
+ # SUCCEED State - Successful completion
793
+ OrderCompleted:
794
+ Type: Succeed
795
+
796
+ # FAIL State - Final failure
797
+ OrderFailed:
798
+ Type: Fail
799
+ Cause: "Order confirmation failed to send"
800
+ Error: "ConfirmationError"
801
+ YAML
802
+
803
+ File.write(@workflow_file, workflow_yaml)
804
+ puts "๐Ÿ“„ Generated enhanced workflow file: #{@workflow_file}"
805
+ end
806
+
807
+ def run_test_cases
808
+ test_cases = [
809
+ {
810
+ name: "๐Ÿ† Premium Order with Parallel Processing",
811
+ input: {
812
+ "order" => {
813
+ "id" => "ORD-PREM-001",
814
+ "total" => 750.00,
815
+ "customer_id" => "CUST-PREM-001",
816
+ "items" => ["premium_item_1", "premium_item_2"],
817
+ "quantity" => 2,
818
+ "premium_customer" => true,
819
+ "payment_method" => "credit_card",
820
+ "shipping" => { "required" => true, "country" => "US" }
821
+ }
822
+ }
823
+ },
824
+ {
825
+ name: "๐Ÿ“ฆ Bulk Order (Testing Retry)",
826
+ input: {
827
+ "order" => {
828
+ "id" => "ORD-BULK-001",
829
+ "total" => 1800.00, # Will trigger payment retry
830
+ "customer_id" => "CUST-BULK-001",
831
+ "items" => ["bulk_item_1"],
832
+ "quantity" => 25,
833
+ "payment_method" => "credit_card",
834
+ "shipping" => { "required" => true, "country" => "US" }
835
+ }
836
+ }
837
+ },
838
+ {
839
+ name: "๐Ÿ’ป Digital Order (No Shipping)",
840
+ input: {
841
+ "order" => {
842
+ "id" => "ORD-DIG-001",
843
+ "total" => 49.99,
844
+ "customer_id" => "CUST-DIG-001",
845
+ "items" => ["ebook"],
846
+ "quantity" => 1,
847
+ "payment_method" => "paypal",
848
+ "shipping" => { "required" => false },
849
+ "digital_product" => { "type" => "ebook" },
850
+ "customer_email" => "customer@example.com"
851
+ }
852
+ }
853
+ },
854
+ {
855
+ name: "๐ŸŒ International Order",
856
+ input: {
857
+ "order" => {
858
+ "id" => "ORD-INT-001",
859
+ "total" => 299.99,
860
+ "customer_id" => "CUST-INT-001",
861
+ "items" => ["international_item"],
862
+ "quantity" => 1,
863
+ "payment_method" => "paypal",
864
+ "shipping" => { "required" => true, "country" => "UK" }
865
+ }
866
+ }
867
+ },
868
+ {
869
+ name: "๐Ÿ’ธ Payment Failure Scenario",
870
+ input: {
871
+ "order" => {
872
+ "id" => "ORD-FAIL-001",
873
+ "total" => 2500.00, # High amount that will fail payment
874
+ "customer_id" => "CUST-FAIL-001",
875
+ "items" => ["expensive_item"],
876
+ "quantity" => 1,
877
+ "payment_method" => "expired_card", # This will cause failure
878
+ "shipping" => { "required" => true, "country" => "US" }
879
+ }
880
+ }
881
+ }
882
+ ]
883
+
884
+ test_cases.each do |test_case|
885
+ puts "\n" + "="*70
886
+ puts "๐Ÿงช #{test_case[:name]}"
887
+ puts "="*70
888
+
889
+ start_time = Time.now
890
+
891
+ begin
892
+ # Load the state machine from YAML
893
+ state_machine = StatesLanguageMachine.from_yaml_file(@workflow_file)
894
+
895
+ # Start execution
896
+ execution = state_machine.start_execution(test_case[:input], "test-#{test_case[:input]['order']['id']}")
897
+
898
+ # Set the executor in context
899
+ execution.context[:task_executor] = @executor
900
+
901
+ # Run the workflow
902
+ execution.run_all
903
+
904
+ execution_time = Time.now - start_time
905
+
906
+ # Display results
907
+ puts "โœ… Workflow completed successfully!"
908
+ puts "๐Ÿ“Š Final Status: #{execution.status}"
909
+ puts "๐Ÿ›ฃ๏ธ Execution Path: #{execution.history.map { |h| h[:state_name] }.join(' โ†’ ')}"
910
+ puts "โฑ๏ธ Execution Time: #{execution_time.round(4)} seconds"
911
+ puts "๐Ÿ“ˆ States Visited: #{execution.history.size}"
912
+
913
+ if execution.output
914
+ puts "๐Ÿ“ฆ Final Output Summary:"
915
+ execution.output.each do |key, value|
916
+ if value.is_a?(Hash)
917
+ puts " - #{key}: #{value.keys.join(', ')}"
918
+ else
919
+ puts " - #{key}: #{value}"
920
+ end
921
+ end
922
+
923
+ # Show parallel results specifically
924
+ if execution.output['inventory_result'] || execution.output['notification_result']
925
+ puts "๐Ÿ”€ Parallel Branch Results:"
926
+ %w[inventory_result notification_result analytics_result loyalty_result].each do |branch|
927
+ if execution.output[branch]
928
+ status = execution.output[branch].keys.first rescue 'unknown'
929
+ puts " - #{branch}: #{status}"
930
+ end
931
+ end
932
+ end
933
+ end
934
+
935
+ rescue => e
936
+ execution_time = Time.now - start_time
937
+ puts "โŒ Workflow failed!"
938
+ puts "๐Ÿ’ฅ Error: #{e.message}"
939
+ if execution
940
+ puts "๐Ÿ›‘ Final Status: #{execution.status}"
941
+ puts "๐Ÿ“ Last State: #{execution.history.last[:state_name]}" if execution.history.any?
942
+ puts "๐Ÿ“ History: #{execution.history.map { |h| h[:state_name] }.join(' โ†’ ')}"
943
+ end
944
+ puts "โฑ๏ธ Execution Time: #{execution_time.round(4)} seconds"
945
+ end
946
+
947
+ puts "\n"
948
+ end
949
+ end
950
+ end
951
+
952
+ # Main execution
953
+ if __FILE__ == $0
954
+ begin
955
+ require 'ruby_slm'
956
+
957
+ puts "๐Ÿš€ Starting Enhanced Complex Workflow Test"
958
+ puts "Testing ALL state types: Pass, Task, Choice, Parallel, Succeed, Fail"
959
+ puts "With retry mechanisms, error handling, and parallel processing"
960
+ puts ""
961
+
962
+ tester = WorkflowTester.new
963
+ tester.run_test_cases
964
+
965
+ puts "๐ŸŽ‰ All tests completed!"
966
+ puts ""
967
+ puts "๐Ÿ“‹ State Types Demonstrated:"
968
+ puts " โœ… Pass - Data transformation"
969
+ puts " โœ… Task - Business logic execution"
970
+ puts " โœ… Choice - Conditional routing"
971
+ puts " โœ… Parallel - Concurrent branch execution"
972
+ puts " โœ… Succeed - Successful termination"
973
+ puts " โœ… Fail - Error termination"
974
+ puts " โœ… Retry - Automatic retry mechanisms"
975
+ puts " โœ… Catch - Error handling blocks"
976
+
977
+ rescue LoadError => e
978
+ puts "โŒ Error: Could not load ruby_slm gem"
979
+ puts "Make sure the gem is installed and in your load path"
980
+ puts "Details: #{e.message}"
981
+ end
982
+ end# frozen_string_literal: true
983
+