@@ -550,11 +550,43 @@ defmodule VirtualClock do
550550 end
551551 end
552552
553+ # Check if a process should be tracked for ACKs
554+ # Only GenServers using VirtualTimeGenServer or VirtualTimeGenStateMachine wrappers will ACK
555+ defp should_track_for_ack? ( pid ) do
556+ case Process . info ( pid , :dictionary ) do
557+ { :dictionary , dict } when is_list ( dict ) ->
558+ has_virtual_clock? ( dict ) && genserver_actor? ( pid , dict )
559+
560+ _ ->
561+ false
562+ end
563+ end
564+
565+ defp has_virtual_clock? ( dict ) do
566+ Keyword . has_key? ( dict , :virtual_clock )
567+ end
568+
569+ defp genserver_actor? ( pid , dict ) do
570+ case Keyword . get ( dict , :"$initial_call" ) do
571+ { VirtualTimeGenServer.Wrapper , _ , _ } -> true
572+ { VirtualTimeGenStateMachine.Wrapper , _ , _ } -> true
573+ _ -> check_current_function_for_gen_server ( pid )
574+ end
575+ end
576+
577+ defp check_current_function_for_gen_server ( pid ) do
578+ case Process . info ( pid , :current_function ) do
579+ { :current_function , { mod , _ , _ } } -> mod in [ :gen_server , :gen_statem ]
580+ _ -> false
581+ end
582+ end
583+
553584 defp advance_loop ( state , target_time , from ) do
554585 # Calculate adaptive timeout based on time advance
555586 # For large advances, use longer timeout (max 30 seconds)
556587 time_advance = target_time - state . current_time
557- ack_timeout_ms =
588+
589+ ack_timeout_ms =
558590 if time_advance > 100_000 do
559591 # For advances > 100s, use adaptive timeout
560592 min ( trunc ( time_advance / 1000 ) , 30_000 )
@@ -565,7 +597,11 @@ defmodule VirtualClock do
565597 # Set up timeout for ack wait - only if we have pending acks
566598 ack_timeout_ref =
567599 if MapSet . size ( state . pending_acks ) > 0 do
568- Process . send_after ( self ( ) , { :ack_timeout , MapSet . to_list ( state . pending_acks ) } , ack_timeout_ms )
600+ Process . send_after (
601+ self ( ) ,
602+ { :ack_timeout , MapSet . to_list ( state . pending_acks ) } ,
603+ ack_timeout_ms
604+ )
569605 else
570606 nil
571607 end
@@ -582,8 +618,16 @@ defmodule VirtualClock do
582618 if MapSet . size ( new_state . pending_acks ) > 0 do
583619 # Still waiting for actors - store caller and wait for acks with adaptive timeout
584620 time_advance = target_time - state . current_time
585- ack_timeout_ms = if time_advance > 100_000 , do: min ( trunc ( time_advance / 1000 ) , 30_000 ) , else: 2000
586- Process . send_after ( self ( ) , { :ack_timeout , MapSet . to_list ( new_state . pending_acks ) } , ack_timeout_ms )
621+
622+ ack_timeout_ms =
623+ if time_advance > 100_000 , do: min ( trunc ( time_advance / 1000 ) , 30_000 ) , else: 2000
624+
625+ Process . send_after (
626+ self ( ) ,
627+ { :ack_timeout , MapSet . to_list ( new_state . pending_acks ) } ,
628+ ack_timeout_ms
629+ )
630+
587631 { :noreply , % { new_state | advance_caller: from , target_time: target_time } }
588632 else
589633 # No pending acks - advance complete!
@@ -599,10 +643,17 @@ defmodule VirtualClock do
599643 if ack_timeout_ref , do: Process . cancel_timer ( ack_timeout_ref )
600644
601645 # Process events at next_time - track who we're sending to for acks
602- actor_pids =
603- Enum . map ( triggered , fn event ->
646+ # Only track GenServer actors that will send ACKs, not regular processes
647+ { actor_pids , _ } =
648+ Enum . reduce ( triggered , { [ ] , [ ] } , fn event , { ack_actors , regular_processes } ->
649+ # Send message immediately
604650 VirtualTimeGenServer . send_immediately ( event . dest , event . message )
605- event . dest
651+
652+ if should_track_for_ack? ( event . dest ) do
653+ { [ event . dest | ack_actors ] , regular_processes }
654+ else
655+ { ack_actors , [ event . dest | regular_processes ] }
656+ end
606657 end )
607658
608659 # Track pending acks and update time
@@ -614,7 +665,10 @@ defmodule VirtualClock do
614665 # Actors are processing - store caller and wait for all acks
615666 # Set up adaptive timeout for the new acks
616667 time_advance = target_time - next_time
617- ack_timeout_ms = if time_advance > 100_000 , do: min ( trunc ( time_advance / 1000 ) , 30_000 ) , else: 2000
668+
669+ ack_timeout_ms =
670+ if time_advance > 100_000 , do: min ( trunc ( time_advance / 1000 ) , 30_000 ) , else: 2000
671+
618672 Process . send_after ( self ( ) , { :ack_timeout , MapSet . to_list ( new_pending ) } , ack_timeout_ms )
619673 { :noreply , % { new_state | advance_caller: from , target_time: target_time } }
620674 else
0 commit comments