Skip to content

Add async processing capability to CMRI $package operation#1060

Open
Chris0296 wants to merge 8 commits into
mainfrom
cor-async-package
Open

Add async processing capability to CMRI $package operation#1060
Chris0296 wants to merge 8 commits 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!

@c-schuler c-schuler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is looking good. I do have a couple change requests listed below.

Additionally, it does not appear that ImplementationGuidePackageProvider (r4) was converted and silently ignores Prefer: respond-async. Perhaps that is still TODO?

Chris0296 and others added 2 commits July 6, 2026 14:34
    - extract detach call from submit
    - preserve authorization flow for async processing path
    - use @PreDestroy in place of shutdown hook
    - Rename IT class prefix from *Test to *IT

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Chris0296 Chris0296 requested a review from c-schuler July 6, 2026 21:43
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Chris0296 Chris0296 marked this pull request as ready for review July 6, 2026 22:23
@Chris0296 Chris0296 force-pushed the cor-async-package branch from fa1b12f to ef0a800 Compare July 7, 2026 15:08

@c-schuler c-schuler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looking better. A couple of regressions noted in the change requests

@sonarqubecloud

sonarqubecloud Bot commented Jul 7, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
56.7% 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.

2 participants