Skip to content

Commit e110445

Browse files
committed
fixed tests
1 parent 15dcd0e commit e110445

File tree

2 files changed

+24
-19
lines changed

2 files changed

+24
-19
lines changed

packages/service-library/src/servicelib/redis/_semaphore_decorator.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,12 @@ async def _periodic_renewer() -> None:
5959
_periodic_renewer(),
6060
name=f"semaphore/autorenewal_{semaphore_key}_{semaphore.instance_id}",
6161
)
62-
63-
# Wait for first renewal to complete (ensures task is running)
6462
await started_event.wait()
6563

66-
# Yield control back to caller
6764
yield
6865

69-
# Cancel renewal task when execution is done
66+
# NOTE: if we do not explicitely await the task inside the context manager
67+
# it sometimes hangs forever (Python issue?)
7068
await cancel_wait_task(renewal_task, max_delay=None)
7169

7270
except BaseExceptionGroup as eg:

packages/service-library/tests/redis/test_semaphore_decorator.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,18 @@ async def test_auto_renewal_lose_semaphore_raises(
120120
capacity=semaphore_capacity,
121121
ttl=short_ttl,
122122
)
123-
async def work_that_should_fail() -> Literal["should not reach here"]:
123+
async def coro_that_should_fail() -> Literal["should not reach here"]:
124124
work_started.set()
125125
# Wait long enough for renewal to be attempted multiple times
126-
await asyncio.sleep(short_ttl.total_seconds() * 4)
126+
await asyncio.sleep(short_ttl.total_seconds() * 100)
127127
return "should not reach here"
128128

129-
task = asyncio.create_task(work_that_should_fail())
129+
task = asyncio.create_task(coro_that_should_fail())
130130
await work_started.wait()
131131

132132
# Wait for the first renewal interval to pass
133133
renewal_interval = short_ttl / 3
134-
await asyncio.sleep(renewal_interval.total_seconds() + 1)
134+
await asyncio.sleep(renewal_interval.total_seconds() * 1.5)
135135

136136
# Find and delete all holder keys for this semaphore
137137
holder_keys = await redis_client_sdk.redis.keys(
@@ -140,8 +140,13 @@ async def work_that_should_fail() -> Literal["should not reach here"]:
140140
assert holder_keys, "Holder keys should exist before deletion"
141141
await redis_client_sdk.redis.delete(*holder_keys)
142142

143-
with pytest.raises(SemaphoreLostError):
144-
await task # This should raise the renewal failure exception
143+
# wait another renewal interval to ensure the renewal fails
144+
await asyncio.sleep(renewal_interval.total_seconds() * 1.5)
145+
146+
# it shall have raised already, do not wait too much
147+
async with asyncio.timeout(renewal_interval.total_seconds()):
148+
with pytest.raises(SemaphoreLostError):
149+
await task
145150

146151

147152
async def test_decorator_with_callable_parameters(
@@ -655,23 +660,21 @@ async def test_context_manager_lose_semaphore_raises(
655660
)
656661
@asynccontextmanager
657662
async def context_manager_that_should_fail():
658-
work_started.set()
659663
yield "data"
660-
# Wait long enough for renewal to be attempted multiple times
661-
await asyncio.sleep(short_ttl.total_seconds() * 4)
662664

663-
async def use_failing_cm():
665+
async def use_failing_cm() -> None:
664666
async with context_manager_that_should_fail() as data:
665667
assert data == "data"
666-
# Keep context active while semaphore will be lost
667-
await asyncio.sleep(short_ttl.total_seconds() * 3)
668+
work_started.set()
669+
# Wait long enough for renewal to be attempted multiple times
670+
await asyncio.sleep(short_ttl.total_seconds() * 100)
668671

669672
task = asyncio.create_task(use_failing_cm())
670673
await work_started.wait()
671674

672675
# Wait for the first renewal interval to pass
673676
renewal_interval = short_ttl / 3
674-
await asyncio.sleep(renewal_interval.total_seconds() + 1)
677+
await asyncio.sleep(renewal_interval.total_seconds() + 1.5)
675678

676679
# Find and delete all holder keys for this semaphore
677680
holder_keys = await redis_client_sdk.redis.keys(
@@ -680,5 +683,9 @@ async def use_failing_cm():
680683
assert holder_keys, "Holder keys should exist before deletion"
681684
await redis_client_sdk.redis.delete(*holder_keys)
682685

683-
with pytest.raises(SemaphoreLostError): # Expected from the ExceptionGroup handling
684-
await task
686+
# wait another renewal interval to ensure the renewal fails
687+
await asyncio.sleep(renewal_interval.total_seconds() * 1.5)
688+
689+
async with asyncio.timeout(renewal_interval.total_seconds()):
690+
with pytest.raises(SemaphoreLostError):
691+
await task

0 commit comments

Comments
 (0)