state_machines 0.100.1 → 0.100.4
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/lib/state_machines/transition.rb +71 -30
- data/lib/state_machines/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b5d883e6f3259de8981a9855e50d6f2d859bbd7e9e10a4cc5b4d91ae3fec65f
|
4
|
+
data.tar.gz: 9185125133d36eeed7ae95875a825e0e9a2e4d73b7de286c65be589965d2613d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4786a92acf6011cc49c6e9f8daa0505d7bfcd26da0d244e351830aed0972ac12656ab39df4f9cf7b35fa4892c7afa02830b7ec0b33876a8624076e60fb273f21
|
7
|
+
data.tar.gz: e87573373f971cea02ebba3dcca45124f49d8ca6354c34756e55fd101deab5649ee349e62b05a3abb7d0fdde9ead78075984a089f7f3070fb4b4768c7af8fcc8
|
@@ -1,6 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module StateMachines
|
4
|
+
# Module to extend Fiber instances for pausable state tracking
|
5
|
+
module PausableFiber
|
6
|
+
attr_accessor :state_machine_fiber_pausable
|
7
|
+
end
|
8
|
+
|
4
9
|
# A transition represents a state change for a specific attribute.
|
5
10
|
#
|
6
11
|
# Transitions consist of:
|
@@ -39,6 +44,7 @@ module StateMachines
|
|
39
44
|
@paused_fiber = nil
|
40
45
|
@resuming = false
|
41
46
|
@continuation_block = nil
|
47
|
+
@fiber_thread_storage = nil
|
42
48
|
|
43
49
|
@event = machine.events.fetch(event)
|
44
50
|
@from_state = machine.states.fetch(from_name)
|
@@ -196,7 +202,8 @@ module StateMachines
|
|
196
202
|
# this is an idempotent call on an already-paused transition. Just return true.
|
197
203
|
return true if @paused_fiber&.alive? && !options[:after]
|
198
204
|
|
199
|
-
#
|
205
|
+
# Always use fibers for compatibility with existing pause/resume functionality
|
206
|
+
# The fiber argument can still be used to explicitly control fiber usage
|
200
207
|
pausable_options = options.key?(:fiber) ? { fiber: options[:fiber] } : {}
|
201
208
|
|
202
209
|
# Check if we're resuming from a pause
|
@@ -283,6 +290,7 @@ module StateMachines
|
|
283
290
|
@paused_fiber = nil
|
284
291
|
@resuming = false
|
285
292
|
@continuation_block = nil
|
293
|
+
@fiber_thread_storage = nil
|
286
294
|
end
|
287
295
|
|
288
296
|
# Determines equality of transitions by testing whether the object, states,
|
@@ -375,41 +383,64 @@ module StateMachines
|
|
375
383
|
# Handle different result types
|
376
384
|
case result
|
377
385
|
when Array
|
378
|
-
# Exception occurred inside the fiber
|
379
386
|
if result[0] == :error
|
380
|
-
#
|
387
|
+
# Exception occurred inside the fiber
|
381
388
|
@paused_fiber = nil
|
382
389
|
raise result[1]
|
383
|
-
end
|
384
|
-
else
|
385
|
-
# Normal flow
|
386
|
-
# Check if fiber is still alive after resume
|
387
|
-
if @paused_fiber.alive?
|
388
|
-
# Still paused, keep the fiber
|
389
|
-
true
|
390
390
|
else
|
391
|
-
#
|
392
|
-
@
|
393
|
-
|
391
|
+
# Normal completion with thread storage export
|
392
|
+
@fiber_thread_storage = result[1] if result.length == 2 && result[1].is_a?(Hash)
|
393
|
+
result_value = result[0]
|
394
394
|
end
|
395
|
+
else
|
396
|
+
# Direct result value (paused or simple completion)
|
397
|
+
result_value = result
|
398
|
+
end
|
399
|
+
|
400
|
+
# Check if fiber is still alive after resume
|
401
|
+
if @paused_fiber.alive?
|
402
|
+
# Still paused, keep the fiber
|
403
|
+
true
|
404
|
+
else
|
405
|
+
# Fiber completed
|
406
|
+
@paused_fiber = nil
|
407
|
+
result_value == :halted
|
395
408
|
end
|
396
409
|
else
|
410
|
+
# Capture current fiber's Thread.current storage to preserve object identity
|
411
|
+
# This is needed for compatibility but has limitations with dynamic assignments
|
412
|
+
parent_fiber_locals = Thread.current.keys.each_with_object({}) do |key, storage|
|
413
|
+
storage[key] = Thread.current[key]
|
414
|
+
end
|
415
|
+
|
397
416
|
# Create a new fiber to run the block
|
398
417
|
fiber = Fiber.new do
|
418
|
+
# Restore parent's Thread.current storage with exact same object references
|
419
|
+
parent_fiber_locals.each do |key, value|
|
420
|
+
Thread.current[key] = value
|
421
|
+
end
|
422
|
+
|
399
423
|
# Mark that we're inside a pausable fiber
|
400
|
-
|
424
|
+
Fiber.current.extend(StateMachines::PausableFiber)
|
425
|
+
Fiber.current.state_machine_fiber_pausable = true
|
401
426
|
begin
|
402
427
|
halted = !catch(:halt) do
|
403
428
|
yield
|
404
429
|
true
|
405
430
|
end
|
406
|
-
|
431
|
+
|
432
|
+
# Export the final thread storage state along with the result
|
433
|
+
thread_storage = Thread.current.keys.each_with_object({}) do |key, storage|
|
434
|
+
storage[key] = Thread.current[key]
|
435
|
+
end
|
436
|
+
|
437
|
+
[halted ? :halted : :completed, thread_storage]
|
407
438
|
rescue StandardError => e
|
408
439
|
# Store the exception for re-raising
|
409
440
|
[:error, e]
|
410
441
|
ensure
|
411
442
|
# Clean up the flag
|
412
|
-
|
443
|
+
Fiber.current.state_machine_fiber_pausable = false
|
413
444
|
end
|
414
445
|
end
|
415
446
|
|
@@ -419,23 +450,28 @@ module StateMachines
|
|
419
450
|
# Handle different result types
|
420
451
|
case result
|
421
452
|
when Array
|
422
|
-
# Exception occurred
|
423
453
|
if result[0] == :error
|
424
|
-
#
|
454
|
+
# Exception occurred
|
425
455
|
@paused_fiber = nil
|
426
456
|
raise result[1]
|
427
|
-
end
|
428
|
-
else
|
429
|
-
# Normal flow
|
430
|
-
# Save if paused
|
431
|
-
if fiber.alive?
|
432
|
-
@paused_fiber = fiber
|
433
|
-
# Return true to indicate paused (treated as halted for flow control)
|
434
|
-
true
|
435
457
|
else
|
436
|
-
#
|
437
|
-
result ==
|
458
|
+
# Normal completion - check if we have thread storage
|
459
|
+
@fiber_thread_storage = result[1] if result.length == 2 && result[1].is_a?(Hash)
|
460
|
+
result_value = result[0]
|
438
461
|
end
|
462
|
+
else
|
463
|
+
# Direct result value (shouldn't happen with our new code)
|
464
|
+
result_value = result
|
465
|
+
end
|
466
|
+
|
467
|
+
# Save if paused
|
468
|
+
if fiber.alive?
|
469
|
+
@paused_fiber = fiber
|
470
|
+
# Return true to indicate paused (treated as halted for flow control)
|
471
|
+
true
|
472
|
+
else
|
473
|
+
# Fiber completed, return whether it was halted
|
474
|
+
result_value == :halted
|
439
475
|
end
|
440
476
|
end
|
441
477
|
end
|
@@ -448,8 +484,9 @@ module StateMachines
|
|
448
484
|
return if @resuming
|
449
485
|
|
450
486
|
# Only yield if we're actually inside a fiber created by pausable
|
451
|
-
# We use a
|
452
|
-
|
487
|
+
# We use a module extension to track this
|
488
|
+
current_fiber = Fiber.current
|
489
|
+
return unless current_fiber.respond_to?(:state_machine_fiber_pausable) && current_fiber.state_machine_fiber_pausable
|
453
490
|
|
454
491
|
Fiber.yield
|
455
492
|
|
@@ -532,6 +569,10 @@ module StateMachines
|
|
532
569
|
def after
|
533
570
|
return if @after_run
|
534
571
|
|
572
|
+
# Restore the fiber's thread storage to ensure consistency
|
573
|
+
# This preserves Thread.current state from before/around callbacks to after callbacks
|
574
|
+
@fiber_thread_storage.each { |key, value| Thread.current[key] = value } if @fiber_thread_storage
|
575
|
+
|
535
576
|
catch(:halt) do
|
536
577
|
type = @success ? :after : :failure
|
537
578
|
machine.callbacks[type].each { |callback| callback.call(object, context, self) }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: state_machines
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.100.
|
4
|
+
version: 0.100.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abdelkader Boudih
|
@@ -135,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
135
|
- !ruby/object:Gem::Version
|
136
136
|
version: '0'
|
137
137
|
requirements: []
|
138
|
-
rubygems_version: 3.6.
|
138
|
+
rubygems_version: 3.6.9
|
139
139
|
specification_version: 4
|
140
140
|
summary: State machines for attributes
|
141
141
|
test_files: []
|