2929)
3030import logging
3131import multiprocess # type: ignore[import-untyped]
32-
32+ import time
3333import pytest
3434
35+ SUBMISSION_COMPLETED_TIMEOUT = 10.0
36+
3537
3638def increment (data : int ) -> int :
3739 return data + 1
@@ -57,7 +59,10 @@ def run_consumer() -> None:
5759 input_iter = range (0 , 100 )
5860
5961 output_iter : Iterator [int ] = producer_client .run_submission (
60- input_iter , chunk_size = 20 , strategic_metadata = {"id" : 42 }
62+ input_iter ,
63+ chunk_size = 20 ,
64+ strategic_metadata = {"id" : 42 },
65+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
6166 )
6267 res = sum (output_iter )
6368
@@ -127,6 +132,7 @@ def run_consumer(_consumer_id: int) -> None:
127132 input_iter ,
128133 chunk_size = chunk_size ,
129134 strategic_metadata = {"id" : 42 , "second_id" : 69 },
135+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
130136 )
131137 res = sum (output_iter )
132138
@@ -144,7 +150,11 @@ def test_empty_submission(opsqueue: OpsqueueProcess) -> None:
144150 )
145151
146152 input_iter : list [int ] = []
147- output_iter : Iterator [int ] = producer_client .run_submission (input_iter , chunk_size = 20 )
153+ output_iter : Iterator [int ] = producer_client .run_submission (
154+ input_iter ,
155+ chunk_size = 20 ,
156+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
157+ )
148158 res = sum (output_iter )
149159 assert res == 0
150160
@@ -179,7 +189,10 @@ def run_consumer() -> None:
179189 input_iter = range (0 , 100 )
180190
181191 output_iter : Iterator [int ] = producer_client .run_submission (
182- input_iter , chunk_size = 20 , serialization_format = serialization_format
192+ input_iter ,
193+ chunk_size = 20 ,
194+ serialization_format = serialization_format ,
195+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
183196 )
184197 res = sum (output_iter )
185198
@@ -222,7 +235,11 @@ def broken_increment(input: int) -> float:
222235 input_iter = range (0 , 100 )
223236
224237 with pytest .raises (SubmissionFailedError ) as exc_info :
225- producer_client .run_submission (input_iter , chunk_size = 20 )
238+ producer_client .run_submission (
239+ input_iter ,
240+ chunk_size = 20 ,
241+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
242+ )
226243
227244 # We expect the intended attributes to be there:
228245 assert isinstance (exc_info .value .failure , str )
@@ -262,7 +279,10 @@ def increment_list(ints: Sequence[int], _chunk: Chunk) -> Sequence[int]:
262279 input_iter = map (lambda i : cbor2 .dumps ([i , i , i ]), range (0 , 10 ))
263280 output_iter : Iterator [list [int ]] = map (
264281 lambda c : cbor2 .loads (c ),
265- producer_client .run_submission_chunks (input_iter ),
282+ producer_client .run_submission_chunks (
283+ input_iter ,
284+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
285+ ),
266286 )
267287 import itertools
268288
@@ -300,7 +320,11 @@ def run_consumer(consumer_id: int) -> None:
300320 n_consumers = 16
301321 with multiple_background_processes (run_consumer , n_consumers ) as _consumers :
302322 input_iter = range (0 , 1000 )
303- output_iter : Iterator [int ] = producer_client .run_submission (input_iter , chunk_size = 100 )
323+ output_iter : Iterator [int ] = producer_client .run_submission (
324+ input_iter ,
325+ chunk_size = 100 ,
326+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
327+ )
304328 res = sum (output_iter )
305329
306330 assert res == sum (range (1 , 1001 ))
@@ -372,7 +396,10 @@ def run_consumer() -> None:
372396
373397 with background_process (run_consumer ):
374398 # Wait for the submission to complete.
375- producer_client .blocking_stream_completed_submission (submission_id )
399+ producer_client .blocking_stream_completed_submission (
400+ submission_id ,
401+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
402+ )
376403 submission = producer_client .get_submission_status (submission_id )
377404 assert submission is not None
378405 assert isinstance (submission .submission , SubmissionCompleted )
@@ -416,7 +443,10 @@ def assert_submission_failed_has_metadata(x: SubmissionFailed) -> None:
416443
417444 with pytest .raises (SubmissionFailedError ) as exc_info :
418445 # Wait for the submission to fail.
419- producer_client .blocking_stream_completed_submission (submission_id )
446+ producer_client .blocking_stream_completed_submission (
447+ submission_id ,
448+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
449+ )
420450 assert_submission_failed_has_metadata (exc_info .value .submission )
421451
422452 submission = producer_client .get_submission_status (submission_id )
@@ -504,7 +534,10 @@ def run_consumer() -> None:
504534
505535 with background_process (run_consumer ):
506536 # Wait for the submission to complete.
507- producer_client .blocking_stream_completed_submission (submission_id )
537+ producer_client .blocking_stream_completed_submission (
538+ submission_id ,
539+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
540+ )
508541 submission = producer_client .get_submission_status (submission_id )
509542 assert submission is not None
510543 assert isinstance (submission .submission , SubmissionCompleted )
@@ -537,7 +570,10 @@ def consume(x: int) -> None:
537570
538571 with background_process (run_consumer ):
539572 with pytest .raises (SubmissionFailedError ):
540- producer_client .blocking_stream_completed_submission (submission_id )
573+ producer_client .blocking_stream_completed_submission (
574+ submission_id ,
575+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
576+ )
541577 # Cancelling the failed submission should fail.
542578 with pytest .raises (SubmissionNotCancellableError ) as exc_info :
543579 producer_client .cancel_submission (submission_id )
@@ -567,7 +603,10 @@ def consume(x: int) -> int | None:
567603
568604 with background_process (run_consumer ):
569605 with pytest .raises (SubmissionFailedError ) as exc_info :
570- producer_client .blocking_stream_completed_submission (submission_id )
606+ producer_client .blocking_stream_completed_submission (
607+ submission_id ,
608+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
609+ )
571610 assert exc_info .value .submission .chunks_done == len (chunks ) - 1
572611
573612
@@ -695,7 +734,10 @@ def run_consumer() -> None:
695734 consumer_client .run_each_op (lambda x : x )
696735
697736 with background_process (run_consumer ):
698- producer_client .blocking_stream_completed_submission (submission_id )
737+ producer_client .blocking_stream_completed_submission (
738+ submission_id ,
739+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
740+ )
699741 assert isinstance (
700742 producer_client .get_submission_status (submission_id ),
701743 SubmissionStatus .Completed ,
@@ -744,7 +786,10 @@ def process_op(x: int) -> int:
744786 # Release the consumer.
745787 can_continue .set ()
746788
747- producer_client .blocking_stream_completed_submission (submission_id )
789+ producer_client .blocking_stream_completed_submission (
790+ submission_id ,
791+ timeout = SUBMISSION_COMPLETED_TIMEOUT ,
792+ )
748793 assert isinstance (
749794 producer_client .get_submission_status (submission_id ),
750795 SubmissionStatus .Completed ,
@@ -778,3 +823,25 @@ def test_cancel_paused(opsqueue: OpsqueueProcess) -> None:
778823 assert isinstance (
779824 producer_client .get_submission_status (submission_id ), SubmissionStatus .Cancelled
780825 )
826+
827+
828+ def test_run_submission_timeout (opsqueue : OpsqueueProcess ) -> None :
829+ url = "file:///tmp/opsqueue/test_run_submission_timeout"
830+ producer_client = ProducerClient (f"localhost:{ opsqueue .port } " , url )
831+
832+ def run_consumer () -> None :
833+ consumer_client = ConsumerClient (f"localhost:{ opsqueue .port } " , url )
834+
835+ def process_op (x : int ) -> int :
836+ time .sleep (2.0 )
837+ return x
838+
839+ consumer_client .run_each_op (process_op )
840+
841+ with background_process (run_consumer ) as _consumer :
842+ with pytest .raises (TimeoutError ):
843+ producer_client .run_submission (
844+ [1 ],
845+ chunk_size = 1 ,
846+ timeout = 0.1 ,
847+ )
0 commit comments