44require "timeout"
55
66class CallerLifecycleTest < ActiveSupport ::TestCase
7+ class BlockingWakeUp
8+ # @rbs @waiting: Thread::Queue
9+ # @rbs @release: Thread::Queue
10+
11+ attr_reader :waiting , :release
12+
13+ # @rbs () -> void
14+ def initialize
15+ @waiting = Queue . new
16+ @release = Queue . new
17+ end
18+
19+ # @rbs () -> void
20+ def signal
21+ end
22+
23+ # @rbs (timeout: Numeric) -> void
24+ def wait ( timeout :)
25+ waiting << timeout
26+ release . pop
27+ end
28+ end
29+
730 class Counter < SolidObjects ::Actor
831 actor_type "caller-lifecycle-counter"
932 attribute :count , default : 0
@@ -36,16 +59,21 @@ def increment(label:)
3659 test "concurrent callers preserve staged effects and ordered state" do
3760 Counter . started = Queue . new
3861 Counter . release = Queue . new
39- enqueued = Queue . new
40- subscription = ActiveSupport :: Notifications . subscribe ( "solid_objects.message.enqueued" ) { enqueued << true }
62+ wake_up = BlockingWakeUp . new
63+ SolidObjects . configuration . wake_up_adapter = wake_up
4164 reference = Counter . ref ( "concurrent" )
4265
4366 first = Thread . new { reference . increment ( label : "first" ) }
4467 assert_equal "first" , Timeout . timeout ( 10 ) { Counter . started . pop }
4568 second = Thread . new { reference . increment ( label : "second" ) }
46- 2 . times { Timeout . timeout ( 10 ) { enqueued . pop } }
69+ Timeout . timeout ( 10 ) { wake_up . waiting . pop }
70+ assert_raises ( ThreadError ) { Counter . started . pop ( true ) }
71+ assert_equal 1 , SolidObjects ::ClaimedMessage . count
72+ assert_equal 1 , SolidObjects ::ReadyMessage . count
73+ assert_empty SolidObjects ::Effect . all
4774 Counter . release << true
4875 assert_equal 1 , Timeout . timeout ( 10 ) { first . value }
76+ wake_up . release << true
4977 assert_equal "second" , Timeout . timeout ( 10 ) { Counter . started . pop }
5078 Counter . release << true
5179 assert_equal 2 , Timeout . timeout ( 10 ) { second . value }
@@ -59,9 +87,9 @@ def increment(label:)
5987 ensure
6088 Counter . release << true if first &.alive?
6189 Counter . release << true if second &.alive?
90+ wake_up &.release &.push ( true ) if second &.alive?
6291 first &.join ( 10 )
6392 second &.join ( 10 )
64- ActiveSupport ::Notifications . unsubscribe ( subscription ) if subscription
6593 end
6694
6795 test "caller re-registers after stale cleanup and process retention" do
0 commit comments