Skip to navigation

Overview

When a FileClassified event is received from the Service Bus, the document-splitter service downloads the original PDF and its classification result, splits the PDF into separate files per classified form, uploads each split to blob storage, saves a manifest, and publishes a FileSplitFile event per output file for downstream processing.


Flow

Service Bus (FileClassified)
│
▼
ClassifiedFileHandler
1. Download classification JSON from blob (classifiedOutputUrl)
2. Download original PDF from blob (internalUrl)
3. For each form in classification → split PDF by page range(s)
4. Upload each split PDF to blob storage (splits/<clientAppId>/splitFiles/)
5. Save manifest JSON to blob (splits/<clientAppId>/splitResults/)
6. Publish FileSplitFileEvent per split file → Service Bus

Key Components

FileResponsibility
src/messaging/handlers/classifiedFileHandler.tsOrchestrates the full split workflow
src/internal/pdf/pdfSplitter.tsSplits a PDF buffer by 1-based page ranges using pdf-lib
src/internal/storage/blobStorageService.tsDownload/upload blob buffers; ensure container exists
src/internal/storage/parseBlobUrl.tsParses Azure blob URLs into container/path/filename parts
src/types/messaging.tsEvent type definitions (FileClassifiedEvent, FileSplitFileEvent, ProblemEvent)
src/types/classification.tsClassification result shape (ClassificationResult, ClassificationForm)

Events

Input – FileClassifiedEvent

{
clientApplicationId: string;
internalUrl: string; // blob URL of the original PDF
classifiedOutputUrl: string; // blob URL of the classification JSON
fileId: string;
timestamp: Date;
}

Output – FileSplitFileEvent (one per split file)

{
clientApplicationId: string;
internalUrl: string; // blob URL of the split PDF
fileLocationUrl: string;
timestamp: Date;
}

Error – ProblemEvent

Published when processing fails. Returns 404 if the blob is not found, 500 for all other errors.


Blob Storage Layout

splits/
<clientApplicationId>/
splitFiles/
<timestamp>_<baseName>_pg<start>-<end>_<formType>.pdf
splitResults/
<timestamp>_<baseName>_splitResult.json ← manifest

Manifest Schema

{
"clientApplicationId": "...",
"fileId": "...",
"parentFileBlobUrl": "...",
"classificationUrl": "...",
"timestamp": "...",
"totalSplitFiles": 3,
"splitFiles": [
{ "fileName": "...", "formType": "...", "formIndex": 0, "pageStart": 1, "pageEnd": 3, "blobUrl": "..." }
]
}

Edge Cases

  • No forms in classification → skipped with a warning, no split produced.
  • Form with no valid page range → skipped with a warning.
  • Multiple page ranges per form → one split file produced per range (concurrent upload).
  • Any processing error → ProblemEvent published; error is rethrown for Service Bus dead-lettering.

Limitations

  • File Type Supported only PDF.

TO-BE: Future Changes

Overview

The direct blob upload from document-splitter will be replaced by delegating file storage to the file-intake service. Document-splitter will call file-intake’s upload endpoint for each split file, and file-intake is responsible for storing the blob and generating a FileId. Document-splitter then publishes the split file event (including the FileId) to the Service Bus.


Updated Flow

Service Bus (FileClassified)
│
▼
Document-Splitter (ClassifiedFileHandler)
1. Download classification JSON from blob (classifiedOutputUrl)
2. Download original PDF from blob (internalUrl)
3. For each form in classification → split PDF by page range(s)
4. POST each split file to file-intake upload endpoint
└─ file-intake stores the child blob + creates FileId
└─ file-intake returns { fileId, internalUrl, hashValue }
5. Save manifest JSON to blob (splits/<clientAppId>/splitResults/)
6. Publish FileSplitFileEvent per split file → split-file topic
└─ message includes FileId returned from file-intake

Current Implementation and To-Be

AreaCurrentTO-BE
Split file storageDocument-splitter uploads directly to blob storageDocument-splitter calls file-intake upload endpoint
FileId generationNot included in split eventsfile-intake creates and returns FileId per split file
internalUrl sourceGenerated locally from blob uploadReturned by file-intake after upload
Split file event payloadNo FileIdIncludes FileId from file-intake response
Service Bus topicsplit-file topicsplit-file topic (unchanged)

Updated Output Event – FileSplitFileEvent

Current

{
clientApplicationId: string;
internalUrl: string;
fileLocationUrl: string;
timestamp: Date;
}

To-Be

{
clientApplicationId: string;
fileId: string; // returned by file-intake after upload
internalUrl: string;
fileLocationUrl: string;
timestamp: Date;
}

file-intake Integration

  • Endpoint: POST /files/child/upload (file-intake service, NEW Endpoint)
  • Request: multipart or binary body containing the split PDF buffer
  • Response: { fileId: string, internalUrl: string, hashValue: string }
  • One HTTP call is made per split file; document-splitter awaits the response before publishing the event.
  • If the file-intake call fails, a ProblemEvent is published and the error is rethrown (same error handling as today).