Skip to content

feat: give customer Loom imports their own importer lane - #3131

Merged
richiemcilroy merged 2 commits into
mainfrom
feat/loom-customer-lane
Oct 24, 2026
Merged

richiemcilroy merged 2 commits into
mainfrom
feat/loom-customer-lane

Conversation

@richiemcilroy

@richiemcilroy richiemcilroy commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Customer Loom imports now get their own lane on the Loom importer, so they no longer wait behind operator redrives and CSV backfills.

flowchart LR
  subgraph web
    D[Dashboard / agent API / mobile / Retry] -->|importPriority: customer| W[import-loom-video workflow]
    R[Internal redrive + CSV routes] -->|importPriority: bulk| W
    C[Recovery crons] -->|lane from the run receipt| W
  end
  W -->|POST /video/import| I
  subgraph I[Loom importer]
    Q1[customer queue] --> S[slots]
    Q2[bulk queue] --> S
  end
Loading
  • Bulk keeps exactly LOOM_IMPORTER_MAX_JOBS slots. Customer imports get LOOM_IMPORTER_CUSTOMER_JOBS extra slots (default 16) on top, and are started first when a general slot frees (apps/media-server/src/loom-importer/app.ts).
  • Bulk never takes a customer slot:
const canStart = (lane: ImportLane) =>
	running.size <
	config.maxActiveJobs +
		(lane === "customer"
			? config.maxCustomerJobs
			: Math.min(runningCustomer, config.maxCustomerJobs));
  • Customer HLS segment fetches jump the shared connection pool (Semaphore.run(work, priority) in fetch.ts).
  • Each lane has its own LOOM_IMPORTER_MAX_QUEUED limit, so a full bulk queue no longer returns SERVER_BUSY to customers.
  • The web app labels operator entry points bulk (loom-import-redrive.ts, api/internal/loom-imports/csv). Everything else, including the agent API and Retry, is customer. The label is stored on metadata.loomImportRun.importPriority so recovery restarts keep it.
  • Only the importer receives importPriority. The media fleet request body is unchanged.
  • Either deploy order is safe: an older importer strips the field, and an importer that gets no label treats the import as bulk, which is today's single FIFO queue.

Benchmark

Same box (c7gd.4xlarge importer host), test importer with 2 general slots, 1 customer slot, 48 shared connections. Each run imports a real 53-minute Loom webinar (HLS, 779 MB) 6 times as bulk; "mixed" adds one customer import of the same video 5 s in. Runs alternated base, new, new, base.

Scenario Metric main This PR
Bulk only all 6 bulk done 13.4 s, 13.5 s 13.6 s, 13.2 s
Mixed customer import, post to done 12.1 s, 12.0 s 3.7 s, 3.7 s
Mixed all 6 bulk done 13.5 s, 13.4 s 14.1 s, 14.3 s
Mixed everything done 17.1 s, 17.0 s 14.1 s, 14.3 s
  • With no customer imports, bulk throughput is unchanged.
  • In the mixed run, bulk finishes about 0.7 s later because the customer import shares the box's bandwidth instead of waiting for the bulk queue to empty.
  • On main the customer wait grows with the size of the bulk queue. Today a customer agent import waited 3 to 7 minutes behind a 1,216-video redrive.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no blocking issues were found.

Summary

Gives customer Loom imports a separate queue and extra running slots.

  • Customer Loom imports start ahead of bulk work.
  • Loom imports keep their customer or bulk lane when they start and restart.

No actionable issues were found. No previous review threads were supplied.

Reviews (2) · Last reviewed commit: "feat(web): label operator Loom imports a..." · Reviewed by Greptile

@richiemcilroy

Copy link
Copy Markdown
Member Author

hey @greptileai, please re-review the PR

@richiemcilroy
richiemcilroy marked this pull request as ready for review October 24, 2026 19:26

@capy-ai capy-ai Bot 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.

Capy found 1 potential issue (1 medium).

View 1 other finding in Capy.

Open in Capy

destination: folderId ? { folderId } : {},
migrationRequestId,
migrationLeaseToken,
importPriority,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Concierge migrations enter the customer lane

Medium Severity

The unchanged importConciergeCsvRows caller in apps/web/actions/loom.ts invokes processLoomCsvRows without importPriority. The admin migration UI dispatches successive CSV batches through this operator-only path, so the undefined value forwarded here becomes customer in processVideoOnMediaServer. A sufficiently large or slow concierge migration can therefore occupy the reserved customer slots and queue ahead of interactive imports, defeating the new isolation. Pass importPriority: "bulk" from the concierge caller, or derive that lane from its migrationRequestId, while retaining the customer default for user imports.

Open in Capy

@richiemcilroy
richiemcilroy merged commit df1fea3 into main Oct 24, 2026
56 checks passed

This branch was successfully deployed

1 active and 1 inactive deployments
Preview – cap-web — f24a7612 Deployed Oct 24, 2026 by vercel[bot]
Preview – cap-status — f24a7612 Deployed Oct 24, 2026 by vercel[bot]
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.

1 participant