|
18 | 18 | Server, |
19 | 19 | TimedOutError, |
20 | 20 | ) |
| 21 | +from servicelib.resilent_long_running._client import AlreadyStartedError |
21 | 22 | from servicelib.resilent_long_running._models import JobUniqueId |
22 | 23 | from servicelib.resilent_long_running.runners.asyncio_tasks import ( |
23 | 24 | AsyncioTasksJobInterface, |
24 | 25 | AsyncTaskRegistry, |
25 | 26 | ) |
| 27 | +from servicelib.utils import limited_gather |
26 | 28 | from settings_library.rabbit import RabbitSettings |
27 | 29 | from settings_library.redis import RedisSettings |
28 | 30 | from tenacity import ( |
@@ -66,6 +68,10 @@ async def some_f() -> None: |
66 | 68 | async def echo_f(data: Any) -> Any: |
67 | 69 | return data |
68 | 70 |
|
| 71 | + @registry.expose() |
| 72 | + async def inc_number_f(number: int) -> int: |
| 73 | + return number + 1 |
| 74 | + |
69 | 75 | @registry.expose() |
70 | 76 | async def raising_f() -> None: |
71 | 77 | msg = "I always raise an error" |
@@ -134,6 +140,25 @@ async def test_workflow( |
134 | 140 | assert type(result) is expected_type |
135 | 141 |
|
136 | 142 |
|
| 143 | +@pytest.mark.parametrize("is_unique", [True, False]) |
| 144 | +async def test_workflow_paralle_calls_to_same_handler( |
| 145 | + server: Server, client: Client, is_unique: bool |
| 146 | +): |
| 147 | + async def _to_run(number: int) -> None: |
| 148 | + result = await client.ensure_result( |
| 149 | + "inc_number_f", |
| 150 | + expected_type=int, |
| 151 | + timeout=timedelta(seconds=30), |
| 152 | + number=number, |
| 153 | + is_unique=is_unique, |
| 154 | + ) |
| 155 | + assert result == number + 1 |
| 156 | + |
| 157 | + count = 100 |
| 158 | + await limited_gather(*(_to_run(number) for number in range(count)), limit=count) |
| 159 | + await _assert_tasks_count(server, count=0) |
| 160 | + |
| 161 | + |
137 | 162 | @pytest.mark.parametrize("is_unique", [True, False]) |
138 | 163 | async def test_timeout_error(server: Server, client: Client, is_unique: bool): |
139 | 164 | with pytest.raises(TimedOutError): |
@@ -319,18 +344,36 @@ async def main(): |
319 | 344 | process.kill() |
320 | 345 |
|
321 | 346 |
|
322 | | -@pytest.mark.parametrize("is_unique", [False]) |
| 347 | +async def test_start_unique_task_twice_is_not_allowed(server: Server, client: Client): |
| 348 | + async def _runner() -> None: |
| 349 | + await client.ensure_result( |
| 350 | + "sleep_for_f", |
| 351 | + expected_type=type(None), |
| 352 | + timeout=timedelta(seconds=30), |
| 353 | + duration=2, |
| 354 | + is_unique=True, |
| 355 | + ) |
| 356 | + |
| 357 | + with pytest.raises(AlreadyStartedError): |
| 358 | + await limited_gather(*(_runner() for _ in range(2)), limit=2) |
| 359 | + |
| 360 | + |
323 | 361 | async def test_cancellation_of_client_can_resume_process( |
324 | 362 | server: Server, |
325 | 363 | client_process: Callable[[Callable[[Client], Awaitable[None]]], Process], |
326 | 364 | client: Client, |
327 | | - is_unique: bool, |
328 | 365 | ): |
329 | 366 | await _assert_tasks_count(server, count=0) |
330 | 367 |
|
| 368 | + # NOTE: only when the task is maked as unique can the client pickup |
| 369 | + # the running handler running on remote once it's restarted |
| 370 | + |
| 371 | + # NOTE: you cannot start the same unique task twice |
| 372 | + # a task is unique when all of it's parameters are the same and is maked as unique |
| 373 | + |
331 | 374 | async def _runner(client_: Client) -> None: |
332 | 375 | await _sleep_for_ensure_result( |
333 | | - client_, retry_count=3, timeout=timedelta(minutes=1), is_unique=is_unique |
| 376 | + client_, retry_count=3, timeout=timedelta(minutes=1), is_unique=True |
334 | 377 | ) |
335 | 378 |
|
336 | 379 | # start task in process |
|
0 commit comments