Skip to content

Add async processing capability to CMRI $package operation#1060

Draft
Chris0296 wants to merge 1 commit into
mainfrom
cor-async-package
Draft

Add async processing capability to CMRI $package operation#1060
Chris0296 wants to merge 1 commit into
mainfrom
cor-async-package

Conversation

@Chris0296

Copy link
Copy Markdown
Collaborator

Adds optional asynchronous handling to the CRMI $package operation so clients can decouple request from response and avoid front-end timeouts on long-running packages.

When a request includes Prefer: respond-async, the operation returns 202 Accepted immediately with a Content-Location header and runs the packaging work on a background thread; the client polls that location for the result. Without the header, behaviour is unchanged (synchronous).

This follows the general FHIR Async Request Pattern handshake. Note the CRMI spec does not define async for $package and its return type is a single Bundle, so completion returns the Bundle inline (a 200) rather than the bulk-data manifest/file-download model, which does not apply here.

Changes

  • PackageJob — job state, published as one immutable Snapshot via an AtomicReference for consistent, thread-safe reads.
  • PackageJobService — in-memory job registry + bounded worker pool, with retention-based purging.
  • AsyncPackageOperationHelper — detects Prefer: respond-async; runs sync or schedules async work, writing the response via HAPI's own RestfulServerUtils.streamResponseAsResource so content negotiation is identical to before.
  • PackageJobStatusProvider — new $package-status system operation (202 while running, 200 + Bundle when done, 500 + OperationOutcome on failure, 404 for unknown jobs).
  • Providers: all $package providers converted to @operation(manualResponse = true) and delegated through the helper. Backward-compatible constructors added, so existing (non-async) wiring keeps working.
  • Wiring: registered the job service, helper, and status provider beans in the R4/DSTU3 PackageOperationConfigs and the dev-server config.
  • Off-thread safety: background work runs against a detached SystemRequestDetails (headers snapshotted) so it's safe to use after the servlet request is recycled.

Tests

  • Integration test (PackageAsyncProviderIT): async kick-off returns 202 + Content-Location; polling yields 200 + Bundle; unknown job returns 404; existing synchronous PackageProviderIT confirms no regression.
  • Unit tests for PackageJob, PackageJobService, and AsyncPackageOperationHelper.

Notes / limitations

  • The job store is in-memory: jobs don't survive a restart. This has been deemed suitable for this implementation.

Implementation based on FHIR async model.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Chris0296 Chris0296 force-pushed the cor-async-package branch from 42ac6f1 to 064c473 Compare July 3, 2026 19:20
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Formatting check succeeded!

@sonarqubecloud

sonarqubecloud Bot commented Jul 3, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
53.5% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

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