Skip to content

fix: serialize Azure TTS backend client lifetimes - #10101

Open
xiongyuyang wants to merge 1 commit into
AstrBotDevs:masterfrom
xiongyuyang:fix/azure-tts-client-lifetime
Open

xiongyuyang wants to merge 1 commit into
AstrBotDevs:masterfrom
xiongyuyang:fix/azure-tts-client-lifetime

Conversation

@xiongyuyang

@xiongyuyang xiongyuyang commented Sep 15, 2026

Copy link
Copy Markdown

Modifications

AzureTTSProvider shares one backend object across requests. Both AzureNativeProvider and OTTSProvider assign _client on context entry and close/reset it on exit. Overlapping get_audio calls can therefore overwrite each other's clients: one request closes the other's client and the original client is leaked.

Add a provider-instance asyncio lock around the complete backend context lifetime. This preserves the existing token/time caches and closes the client before another synthesis enters. Requests using the same provider now queue; separate provider instances remain independent.

  • This is NOT a breaking change.

Screenshots or Test Results

python -m pytest tests/unit/test_azure_tts_concurrency.py -q -p no:cacheprovider

Before the fix: all 6 regression cases failed (missing client on successful synthesis or unclosed client after failure/cancellation).
After the fix: 6 passed, 1 existing audioop deprecation warning on Windows/Python 3.12.

Tests drive the public AzureTTSProvider.get_audio entry point and real HTTP client contexts for native Azure and OTTS. Only synthesis execution is mocked to control overlapping calls, errors and cancellation. No external API was called. Ruff check and commit hooks passed.

Checklist

  • Tested, with verification steps and results above.
  • No new dependencies.
  • No malicious code.
  • New feature discussion: not applicable (bug fix).

Summary by Sourcery

Serialize synthesis lifetimes for each Azure TTS provider instance to preserve backend client isolation and cleanup under concurrent requests.

Bug Fixes:

  • Prevent overlapping Azure TTS requests from replacing or prematurely closing each other’s backend clients.
  • Ensure native Azure and OTTS clients are closed correctly across successful, failed, and cancelled syntheses.

Tests:

  • Add concurrency regression coverage for native Azure and OTTS synthesis across success, error, and cancellation scenarios.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@kilisamemarisaaa kilisamemarisaaa left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at head 134663a. The provider-instance asyncio lock covers the entire mutable backend context lifetime, so overlapping calls cannot replace or close each other's native Azure/OTTS clients; separate provider instances remain independent. Exact-head Windows/Python 3.12 test run passed 6 cases across native/OTTS success, error, and cancellation paths (4 existing warnings); Ruff passed. Tests drive the public get_audio entry point and verify distinct clients are closed after each outcome. No lifecycle or cleanup blocker found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants