66
77import asyncio
88import urllib .parse
9+ from collections .abc import AsyncIterator
910from datetime import datetime
10- from typing import AsyncIterator , Final
11+ from typing import Any , Final
1112
1213import pytest
1314from faker import Faker
2425 TaskStatus ,
2526)
2627from servicelib .long_running_tasks ._task import TasksManager , start_task
28+ from tenacity import TryAgain
2729from tenacity ._asyncio import AsyncRetrying
2830from tenacity .retry import retry_if_exception_type
2931from tenacity .stop import stop_after_delay
3032from tenacity .wait import wait_fixed
3133
32- _RETRY_PARAMS = dict (
33- reraise = True ,
34- wait = wait_fixed (0.1 ),
35- stop = stop_after_delay (60 ),
36- retry = retry_if_exception_type (AssertionError ),
37- )
34+ _RETRY_PARAMS : dict [ str , Any ] = {
35+ " reraise" : True ,
36+ " wait" : wait_fixed (0.1 ),
37+ " stop" : stop_after_delay (60 ),
38+ " retry" : retry_if_exception_type (( AssertionError , TryAgain ) ),
39+ }
3840
3941
4042async def a_background_task (
@@ -47,7 +49,8 @@ async def a_background_task(
4749 await asyncio .sleep (1 )
4850 task_progress .update (percent = ProgressPercent ((i + 1 ) / total_sleep ))
4951 if raise_when_finished :
50- raise RuntimeError ("raised this error as instructed" )
52+ msg = "raised this error as instructed"
53+ raise RuntimeError (msg )
5154
5255 return 42
5356
@@ -59,7 +62,8 @@ async def fast_background_task(task_progress: TaskProgress) -> int:
5962
6063async def failing_background_task (task_progress : TaskProgress ):
6164 """this task does nothing and returns a constant"""
62- raise RuntimeError ("failing asap" )
65+ msg = "failing asap"
66+ raise RuntimeError (msg )
6367
6468
6569TEST_CHECK_STALE_INTERVAL_S : Final [float ] = 1
@@ -75,42 +79,37 @@ async def tasks_manager() -> AsyncIterator[TasksManager]:
7579 await tasks_manager .close ()
7680
7781
78- async def test_unchecked_task_is_auto_removed (tasks_manager : TasksManager ):
82+ @pytest .mark .parametrize ("check_task_presence_before" , [True , False ])
83+ async def test_task_is_auto_removed (
84+ tasks_manager : TasksManager , check_task_presence_before : bool
85+ ):
7986 task_id = start_task (
8087 tasks_manager ,
8188 a_background_task ,
8289 raise_when_finished = False ,
8390 total_sleep = 10 * TEST_CHECK_STALE_INTERVAL_S ,
8491 )
85- await asyncio .sleep (2 * TEST_CHECK_STALE_INTERVAL_S + 1 )
86- async for attempt in AsyncRetrying (** _RETRY_PARAMS ):
87- with attempt :
88- with pytest .raises (TaskNotFoundError ):
89- tasks_manager .get_task_status (task_id , with_task_context = None )
90- with pytest .raises (TaskNotFoundError ):
91- tasks_manager .get_task_result (task_id , with_task_context = None )
92- with pytest .raises (TaskNotFoundError ):
93- tasks_manager .get_task_result_old (task_id )
9492
93+ if check_task_presence_before :
94+ # immediately after starting the task is still there
95+ task_status = tasks_manager .get_task_status (task_id , with_task_context = None )
96+ assert task_status
9597
96- async def test_checked_once_task_is_auto_removed (tasks_manager : TasksManager ):
97- task_id = start_task (
98- tasks_manager ,
99- a_background_task ,
100- raise_when_finished = False ,
101- total_sleep = 10 * TEST_CHECK_STALE_INTERVAL_S ,
102- )
103- # check once (different branch in code)
104- tasks_manager .get_task_status (task_id , with_task_context = None )
105- await asyncio .sleep (2 * TEST_CHECK_STALE_INTERVAL_S + 1 )
98+ # wait for task to be automatically removed
99+ # meaning no calls via the manager methods are received
106100 async for attempt in AsyncRetrying (** _RETRY_PARAMS ):
107101 with attempt :
108- with pytest .raises (TaskNotFoundError ):
109- tasks_manager .get_task_status (task_id , with_task_context = None )
110- with pytest .raises (TaskNotFoundError ):
111- tasks_manager .get_task_result (task_id , with_task_context = None )
112- with pytest .raises (TaskNotFoundError ):
113- tasks_manager .get_task_result_old (task_id )
102+ for tasks in tasks_manager ._tasks_groups .values (): # noqa: SLF001
103+ if task_id in tasks :
104+ msg = "wait till no element is found any longer"
105+ raise TryAgain (msg )
106+
107+ with pytest .raises (TaskNotFoundError ):
108+ tasks_manager .get_task_status (task_id , with_task_context = None )
109+ with pytest .raises (TaskNotFoundError ):
110+ tasks_manager .get_task_result (task_id , with_task_context = None )
111+ with pytest .raises (TaskNotFoundError ):
112+ tasks_manager .get_task_result_old (task_id )
114113
115114
116115async def test_checked_task_is_not_auto_removed (tasks_manager : TasksManager ):
@@ -182,7 +181,9 @@ async def not_unique_task(task_progress: TaskProgress):
182181
183182
184183def test_get_task_id ():
185- assert TasksManager ._create_task_id ("" ) != TasksManager ._create_task_id ("" )
184+ obj1 = TasksManager ._create_task_id ("" ) # noqa: SLF001
185+ obj2 = TasksManager ._create_task_id ("" ) # noqa: SLF001
186+ assert obj1 != obj2
186187
187188
188189async def test_get_status (tasks_manager : TasksManager ):
@@ -248,7 +249,7 @@ async def test_get_result_old_finished_with_error(tasks_manager: TasksManager):
248249 assert task_result .result is None
249250 assert task_result .error is not None
250251 assert task_result .error .startswith (f"Task { task_id } finished with exception:" )
251- assert 'raise RuntimeError( "failing asap")' in task_result .error
252+ assert "failing asap" in task_result .error
252253
253254
254255async def test_get_result_task_was_cancelled_multiple_times (
@@ -364,7 +365,7 @@ async def test_list_tasks(tasks_manager: TasksManager):
364365 NUM_TASKS = 10
365366 task_ids = []
366367 for _ in range (NUM_TASKS ):
367- task_ids .append (
368+ task_ids .append ( # noqa: PERF401
368369 start_task (
369370 tasks_manager = tasks_manager ,
370371 task = a_background_task ,
0 commit comments