Skip to content

TSA-281: [BE] Queue the first pages while ingest is still splitting - #344

Open
IgnacioRB wants to merge 21 commits into
mainfrom
feat/TSA-281-queue-pages-ingest-still-splitting
Open

IgnacioRB wants to merge 21 commits into
mainfrom
feat/TSA-281-queue-pages-ingest-still-splitting

Conversation

@IgnacioRB

Copy link
Copy Markdown
Collaborator

Closes #281

Summary

Implemented incremental page queueing during document ingestion to allow earlier processing and transcription of pages while the document ingestion is taking place. The goal of this change is to enable users to access the document's first transcription once ingestion has started, instead of waiting for the entire action to finish.
During the ingestion process, users can already begin confirming page transcriptions using a sliding window of 5 pages. As correct transcriptions are confirmed, the next pending pages are queued, ensuring a maximum of 5 pages in flight while the rest remain in a PENDING state.
Blank pages continue to be skipped, and when the ingestion process is paused or stopped, new pages stop being queued.
With this, the first page of a 30-page document will have its transcription within the first 5 seconds (in my case), compared to the 46 seconds it takes on the main branch.

  • Measurement on main: 30 pages: 9s 7 pages created, 21s 16, 32s 25, 39s first page queued, 46s first page transcribed.
  • With these changes on this branch: 30 pages: 9s 7 pages created, 5s first page queued and instantly transcribed.

Changes

BE:

  • Integrated page queueing directly into the preparePages loop using refillPageWindow instead of waiting until the entire document ingestion finishes.
  • Added defensive guards to instantly halt queueing if a document hits a BUDGET_STOP or PAUSED status mid-ingest (esto a pesar de que durante una ingestión no se puede pausar).
  • Preserved existing blank page filtering and ensured that reprocessing or re-attempting skips already existing pages safely.

@IgnacioRB IgnacioRB added this to the transcripta-release-4 milestone Sep 21, 2026
@IgnacioRB IgnacioRB self-assigned this Sep 21, 2026
@IgnacioRB IgnacioRB added the backend Backend application label Sep 21, 2026
@IgnacioRB
IgnacioRB force-pushed the feat/TSA-281-queue-pages-ingest-still-splitting branch from 6672005 to badb277 Compare September 21, 2026 07:01
Comment thread apps/backend/src/modules/documents/document.service.ts Outdated
Comment thread apps/backend/src/modules/documents/document.service.ts Outdated

@yurii-tymoshevskyi yurii-tymoshevskyi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

in document.repository.ts add guard to markDoneIfAllPagesClosed versus INGESTING status, because in case first page fails, then the document will be DONE

Image

@IgnacioRB

Copy link
Copy Markdown
Collaborator Author

in document.repository.ts add guard to markDoneIfAllPagesClosed versus INGESTING status, because in case first page fails, then the document will be DONE

Image

@yurii-tymoshevskyi Done. Thanks for the suggestion.

Comment on lines +330 to +337
await DocumentModel.transaction(async (trx) => {
const newlyQueuedPages = await refillPageWindow({
documentId,
pageRepository: this.pageRepository,
quantity: PAGES_TO_QUEUE,
trx,
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

its a condition race with worker
pageTranscribeQueue.add is called inside the transaction, so the job can be picked up before the QUEUED status is committed.
The worker then sees the page as PENDING, the claim updates 0 rows, the job is skipped, and the page stays QUEUED forever.
fix:

const newlyQueuedPages = await DocumentModel.transaction(
	async (trx) =>
		await refillPageWindow({
			documentId,
			pageRepository: this.pageRepository,
			quantity: PAGES_TO_QUEUE,
			trx,
		}),
);

await Promise.all(
	newlyQueuedPages.map((queuedPage) => {
		const { id, pageNo } = queuedPage.toObject();

		return this.pageTranscribeQueue.add({
			documentId,
			pageId: id,
			pageNo,
		});
	}),
);

Comment on lines +322 to +328
if (
!currentDocument ||
currentDocument.status === DocumentStatus.BUDGET_STOP ||
currentDocument.status === DocumentStatus.PAUSED
) {
break;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

BUDGET_STOP can be set mid-ingest.
This break exits the whole loop, so the remaining pages are never created, but finalizeIngest still saves the full pageCount.
After raising the budget and resuming, the document would be missing pages.

@RomanNabukhotniidev

Copy link
Copy Markdown
Collaborator

pls resolve this as first

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

Labels

backend Backend application

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

[BE] Queue the first pages while ingest is still splitting

3 participants