lib/finite_machine/observer.rb in finite_machine-0.14.0 vs lib/finite_machine/observer.rb in finite_machine-0.14.1

- old
+ new

@@ -1,7 +1,9 @@ # frozen_string_literal: true +require "securerandom" + require_relative "async_call" require_relative "callable" require_relative "hook_event" require_relative "hooks" require_relative "message_queue" @@ -11,24 +13,10 @@ module FiniteMachine # A class responsible for observing state changes class Observer < GenericDSL include Safety - # Clean up callback queue - # - # @api private - def self.cleanup_callback_queue - proc do - begin - if callback_queue.alive? - callback_queue.shutdown - end - rescue MessageQueueDeadError - end - end - end - # The current state machine attr_reader :machine # The hooks to trigger around the transition lifecycle. attr_reader :hooks @@ -42,17 +30,12 @@ def initialize(machine) @machine = machine @hooks = Hooks.new @machine.subscribe(self) - ObjectSpace.define_finalizer(self, self.class.cleanup_callback_queue) end - def callback_queue - @callback_queue ||= MessageQueue.new - end - # Evaluate in current context # # @api private def call(&block) instance_eval(&block) @@ -200,9 +183,38 @@ # @api private def defer(callable, trans_event, *data) async_call = AsyncCall.new(machine, callable, trans_event, *data) callback_queue.start unless callback_queue.running? callback_queue << async_call + end + + # Get an existing callback queue or create a new one + # + # @return [FiniteMachine::MessageQueue] + # + # @api private + def callback_queue + @callback_queue ||= MessageQueue.new.tap do + @queue_id = SecureRandom.uuid + ObjectSpace.define_finalizer(@queue_id, proc do + cleanup_callback_queue + end) + end + end + + # Clean up the callback queue + # + # @return [Boolean, nil] + # + # @api private + def cleanup_callback_queue + ObjectSpace.undefine_finalizer(@queue_id) if @queue_id + return unless @callback_queue && callback_queue.alive? + + begin + callback_queue.shutdown + rescue MessageQueueDeadError + end end # Create callable instance # # @api private