Skip to content

perf: Azure and Google vision providers read local image bytes on the event loop #1232

Description

@groupthinking

Problem

BaseCloudAI.analyze_image is implemented by three providers. #1205 moved the AWS implementation's local-file read off the event loop. The Azure and Google implementations still call blocking open(...).read() directly inside async def, so the calling task holds the event loop for the entire duration of a synchronous disk read.

Method File Line Blocking call
AzureVision._prepare_image_input src/youtube_extension/integrations/cloud_ai/providers/azure_vision.py 255-256 open(image_url, 'rb').read()
GoogleCloudAI.analyze_image src/youtube_extension/integrations/cloud_ai/providers/google_cloud.py 185-186 open(image_url, 'rb').read()

Both sites are on the local file branch only; the http:///https:// branches hand the URL to the SDK and are unaffected.

While the loop is blocked, every other coroutine in the process is stalled — not just the caller. On a cold page cache, a network filesystem, or a large frame dump, a single read can stall the loop for tens to hundreds of milliseconds.

Reachability evidence

Reported honestly, because it constrains the claim this issue can make:

  • analyze_image is not currently reachable from an HTTP route. cloud_ai_routes.py is mounted in main.py:173 but exposes only /analyze/video, /analyze/batch, and /analyze/multi-provider. There is no image endpoint.
  • grep -rn "analyze_image" src/ returns only the three provider definitions plus the abstract declaration in base.py:108. There are no in-tree callers.
  • Therefore this is a library-surface defect on a public, abstract-contract method, not a live production hot path. No production latency claim is made.

What does justify the change:

  • analyze_image is part of the BaseCloudAI public contract (base.py:108), so it is callable by any consumer of the integration package.
  • perf(cloud-ai): run AWS Rekognition boto3 calls off the event loop #1205 already established that this exact defect, in this exact method, is worth fixing — it was merged for AWSRekognition. Leaving two of three implementations blocking makes the contract inconsistent: identical calls have different event-loop safety depending on which provider is configured.
  • The fix is mechanical, has a merged in-repo precedent to copy, and carries no behavioural change.

Acceptance criteria

  • Azure and Google local-file reads execute in a worker thread, not on the event loop.
  • Returned bytes are byte-for-byte identical to today for the same input.
  • The http/https branches are untouched.
  • Regression tests prove the read runs on a non-loop thread, asserted by thread identity rather than wall-clock timing.
  • Existing TestAzureVisionPrepareImageInput and TestGoogleCloudAIAnalyzeImage tests pass unmodified.
  • No new dependencies.

Proposed fix

Reuse the pattern merged in #1205 (aws_rekognition.py:109-112, :487): a module-level _read_file_bytes(path) -> bytes helper invoked via await asyncio.to_thread(...).

Activity

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

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions