Skip to content

A UMAP projection cannot be interrupted by stop(), and has no cap on points fed to it #75

Description

@lstein

Summary

_process_projection (invokeai/app/services/image_index/image_index_default.py) calls compute_umap, which never checks _stop_event. stop() joins the worker with a 10s timeout, so shutting down mid-projection blocks for the full 10s, then abandons the daemon thread and logs "did not stop within 10s (likely mid-encode)" — which now misattributes the cause, since it may well be mid-projection.

Unlike clustering, which is capped at MAX_CLUSTERED_POINTS = 50_000, there is no cap on the point count fed to UMAP, and get_embeddings materializes the whole (N, D) matrix in RAM first. A real fit over a large gallery takes minutes and blocks all embedding for that entire duration.

Reproduction

Monkeypatch compute_umap to sleep 20s, request a projection, call stop():

measured: 10.0 s blocked
after:    _worker.is_alive() is True
log:      "did not stop within 10s (likely mid-encode)"

Suggested direction

  • Give compute_umap a cooperative cancellation check, or run it somewhere the join does not depend on.
  • Cap the point count fed to UMAP (or subsample above a threshold), mirroring MAX_CLUSTERED_POINTS.
  • Broaden the log message so it does not blame encoding for a projection stall.

Related

Overlaps #71 (worker abandoned on stop, post-shutdown writes) — same 10s join, different blocking operation. Worth fixing together.

Context

Found during adversarial review of PR #37, deferred as it needs a design decision rather than a local fix. Not user-reachable while image_index_enabled defaults to False.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions