Skip to content

Commit 80aff6c

Browse files
committed
fix(accent): address review cancellation edge cases
1 parent 9827bd8 commit 80aff6c

4 files changed

Lines changed: 37 additions & 15 deletions

File tree

api/accent/preprocess.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -310,10 +310,11 @@ def cap_chunk_length(chunk: str, token_boundaries: set[int] | None = None) -> li
310310
r"hz|db|nm|m|g|l|w|v|a|s|h)"
311311
)
312312
NUMERIC_UNIT_RE = re.compile(rf"^{_NUMERIC_UNIT_BODY}$", re.IGNORECASE)
313-
# Do not retain a unit-looking substring inside an ASCII identifier (for
314-
# example Model10mph or abc53mmdef) when hiding English from OpenJTalk.
313+
# Do not retain a unit-looking substring inside an ASCII identifier or compound
314+
# (for example Model10mph, abc53mmdef, or RTX-4090m) when hiding English from
315+
# OpenJTalk. Dots and hyphens are identifier bridges throughout the pipeline.
315316
_NUMERIC_UNIT_TEXT_RE = re.compile(
316-
rf"(?<![A-Za-z0-9_]){_NUMERIC_UNIT_BODY}(?![A-Za-z0-9_])", re.IGNORECASE
317+
rf"(?<![A-Za-z0-9_.-]){_NUMERIC_UNIT_BODY}(?![A-Za-z0-9_.-])", re.IGNORECASE
317318
)
318319

319320

api/accent/routes.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,18 @@ async def _mark_accent_until_disconnect(
106106

107107
processing = asyncio.create_task(_mark_accent(request))
108108
disconnected = asyncio.create_task(_wait_for_disconnect(raw_request.receive))
109-
done, _pending = await asyncio.wait(
110-
{processing, disconnected}, return_when=asyncio.FIRST_COMPLETED
111-
)
112-
if processing in done:
113-
disconnected.cancel()
114-
await asyncio.gather(disconnected, return_exceptions=True)
115-
return await processing
109+
try:
110+
done, _pending = await asyncio.wait(
111+
{processing, disconnected}, return_when=asyncio.FIRST_COMPLETED
112+
)
113+
if processing in done:
114+
return await processing
116115

117-
processing.cancel()
118-
await asyncio.gather(processing, return_exceptions=True)
119-
raise asyncio.CancelledError
116+
raise asyncio.CancelledError
117+
finally:
118+
processing.cancel()
119+
disconnected.cancel()
120+
await asyncio.gather(processing, disconnected, return_exceptions=True)
120121

121122

122123
async def _wait_for_disconnect(receive: Receive) -> None:

tests/test_preprocess_regressions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414

1515
def test_clean_hidden_english_keeps_only_standalone_numeric_units() -> None:
1616
assert clean_hidden_english("Model10mph猫 abc53mmdef猫") == "10猫 53猫"
17+
assert clean_hidden_english("RTX-4090m猫 53mm-pro猫") == "-4090猫 53-猫"
1718
assert clean_hidden_english("53mm猫 3kgの荷物") == "53mm猫 3kgの荷物"
19+
assert clean_hidden_english("-53mm猫") == "-53mm猫"
1820

1921

2022
def _word(surface: str) -> WordAccentResult:

tests/test_request_limits.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,33 @@ async def scenario() -> None:
135135
limiter = threading.BoundedSemaphore(1)
136136
monkeypatch.setattr(routes, "_REQUEST_LIMITER", limiter)
137137
monkeypatch.setattr(routes, "ACCENT_REQUEST_TIMEOUT_SECONDS", 0.01)
138+
processing_cancelled = asyncio.Event()
139+
receive_cancelled = asyncio.Event()
138140

139141
async def never_finishes(_request: Request) -> None:
140-
await asyncio.Event().wait()
142+
try:
143+
await asyncio.Event().wait()
144+
except asyncio.CancelledError:
145+
processing_cancelled.set()
146+
raise
147+
148+
async def never_disconnects() -> Message:
149+
try:
150+
await asyncio.Event().wait()
151+
except asyncio.CancelledError:
152+
receive_cancelled.set()
153+
raise
141154

142155
monkeypatch.setattr(routes, "_mark_accent", never_finishes)
156+
raw_request = cast(
157+
StarletteRequest, SimpleNamespace(receive=never_disconnects)
158+
)
143159

144160
with pytest.raises(HTTPException) as caught:
145-
await routes.mark_accent(Request(text="猫"), _raw_request())
161+
await routes.mark_accent(Request(text="猫"), raw_request)
146162
assert caught.value.status_code == 504
163+
assert processing_cancelled.is_set()
164+
assert receive_cancelled.is_set()
147165
assert limiter.acquire(blocking=False)
148166
limiter.release()
149167

0 commit comments

Comments
 (0)