state_machines 0.100.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b240916b3b1592fd9980f8dc7583dac5b9af93cf38c193ffb6e2427f3f15f6c0
4
- data.tar.gz: ea38fc11bd6619335415d3a90b92f7f5909df03e5fd087aaf14716dca977d847
3
+ metadata.gz: 7b5d883e6f3259de8981a9855e50d6f2d859bbd7e9e10a4cc5b4d91ae3fec65f
4
+ data.tar.gz: 9185125133d36eeed7ae95875a825e0e9a2e4d73b7de286c65be589965d2613d
5
5
  SHA512:
6
- metadata.gz: 80517f65fa434f346e552677e08cdd6b04e3d573eef756d058645a4d067bb1dd21331d86d657b0df429cfc3157d48cff3bfe594bb7bcb79f4a34b89cf880150c
7
- data.tar.gz: '01874fcbb634ec7daf80bd3a5d87169644916ebb71e4bbfaaf1891ce53beac963261e2684df288b8aaedf057dae66e64f3167bdd6a676b095562096edbf25c42'
6
+ metadata.gz: 4786a92acf6011cc49c6e9f8daa0505d7bfcd26da0d244e351830aed0972ac12656ab39df4f9cf7b35fa4892c7afa02830b7ec0b33876a8624076e60fb273f21
7
+ data.tar.gz: e87573373f971cea02ebba3dcca45124f49d8ca6354c34756e55fd101deab5649ee349e62b05a3abb7d0fdde9ead78075984a089f7f3070fb4b4768c7af8fcc8
@@ -44,6 +44,7 @@ module StateMachines
44
44
  @paused_fiber = nil
45
45
  @resuming = false
46
46
  @continuation_block = nil
47
+ @fiber_thread_storage = nil
47
48
 
48
49
  @event = machine.events.fetch(event)
49
50
  @from_state = machine.states.fetch(from_name)
@@ -201,7 +202,8 @@ module StateMachines
201
202
  # this is an idempotent call on an already-paused transition. Just return true.
202
203
  return true if @paused_fiber&.alive? && !options[:after]
203
204
 
204
- # Extract pausable options
205
+ # Always use fibers for compatibility with existing pause/resume functionality
206
+ # The fiber argument can still be used to explicitly control fiber usage
205
207
  pausable_options = options.key?(:fiber) ? { fiber: options[:fiber] } : {}
206
208
 
207
209
  # Check if we're resuming from a pause
@@ -288,6 +290,7 @@ module StateMachines
288
290
  @paused_fiber = nil
289
291
  @resuming = false
290
292
  @continuation_block = nil
293
+ @fiber_thread_storage = nil
291
294
  end
292
295
 
293
296
  # Determines equality of transitions by testing whether the object, states,
@@ -380,27 +383,43 @@ module StateMachines
380
383
  # Handle different result types
381
384
  case result
382
385
  when Array
383
- # Exception occurred inside the fiber
384
386
  if result[0] == :error
385
- # Clean up state before re-raising
387
+ # Exception occurred inside the fiber
386
388
  @paused_fiber = nil
387
389
  raise result[1]
388
- end
389
- else
390
- # Normal flow
391
- # Check if fiber is still alive after resume
392
- if @paused_fiber.alive?
393
- # Still paused, keep the fiber
394
- true
395
390
  else
396
- # Fiber completed
397
- @paused_fiber = nil
398
- result == :halted
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]
399
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
400
408
  end
401
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
+
402
416
  # Create a new fiber to run the block
403
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
+
404
423
  # Mark that we're inside a pausable fiber
405
424
  Fiber.current.extend(StateMachines::PausableFiber)
406
425
  Fiber.current.state_machine_fiber_pausable = true
@@ -409,7 +428,13 @@ module StateMachines
409
428
  yield
410
429
  true
411
430
  end
412
- halted ? :halted : :completed
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]
413
438
  rescue StandardError => e
414
439
  # Store the exception for re-raising
415
440
  [:error, e]
@@ -425,23 +450,28 @@ module StateMachines
425
450
  # Handle different result types
426
451
  case result
427
452
  when Array
428
- # Exception occurred
429
453
  if result[0] == :error
430
- # Clean up state before re-raising
454
+ # Exception occurred
431
455
  @paused_fiber = nil
432
456
  raise result[1]
433
- end
434
- else
435
- # Normal flow
436
- # Save if paused
437
- if fiber.alive?
438
- @paused_fiber = fiber
439
- # Return true to indicate paused (treated as halted for flow control)
440
- true
441
457
  else
442
- # Fiber completed, return whether it was halted
443
- result == :halted
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]
444
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
445
475
  end
446
476
  end
447
477
  end
@@ -539,6 +569,10 @@ module StateMachines
539
569
  def after
540
570
  return if @after_run
541
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
+
542
576
  catch(:halt) do
543
577
  type = @success ? :after : :failure
544
578
  machine.callbacks[type].each { |callback| callback.call(object, context, self) }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StateMachines
4
- VERSION = '0.100.2'
4
+ VERSION = '0.100.4'
5
5
  end
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.2
4
+ version: 0.100.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih