Skip to content

Batch Transfer 1.0.1-RC — parallel Clone/Reimport, query hardening, UI fixes#7

Merged
kelseym merged 7 commits into
mainfrom
v1-ui-and-performance-optimizations
Jun 25, 2026
Merged

Batch Transfer 1.0.1-RC — parallel Clone/Reimport, query hardening, UI fixes#7
kelseym merged 7 commits into
mainfrom
v1-ui-and-performance-optimizations

Conversation

@kelseym

@kelseym kelseym commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Moves Reimport and Clone off the single sequential loop onto JMS queues so a batch
processes concurrently, hardens the listing query against SQL injection, unifies
workflow-history messages across all three operations, and fixes two UI issues.
Consumer concurrency is admin-tunable, with defaults chosen from profiling (below).
No breaking changes to the /xapi/transfer request format — the new queue-settings
endpoint is additive. Targets XNAT 1.9.3.3 / JDK 8.

Major changes

Parallel processing via JMS queues (#6 )

  • Reimport is dispatched per image session and Clone per subject onto in-process
    (vm://) JMS queues, replacing the single sequential batchTransfer loop.
  • A new in-memory BatchTransferMonitor fans results back in and emits exactly one
    terminal Transfer Complete / Warning event per batch, once every item across every
    operation has finished.
  • Admin-tunable consumer concurrency — new site-admin settings plus
    GET/POST /xapi/batch_transfer/jms_queues. Defaults Reimport 4–8, Clone 1–2;
    set min = max = 1 for a serial kill-switch.

Operation-aware batch routing

  • A batch containing a mix of Share / Clone / Reimport items is now split by operation and
    each group routed to its correct path (Reimport queue, Clone queue, or in-process
    sequential for Share). Previously the batch assumed a single operation type.

Clone file-copy optimization

  • The archive directory copy no longer opens every file to test whether it is a catalog;
    only catalog/XML files are read and the rest are hard-linked directly — sharply fewer
    syscalls on large multi-scan sessions.

Unified workflow history

  • The completed-action workflow on the source item now uses one consistent past-tense
    label for all three operations: "Cloned / Shared / Reimported <item> to project <dest>".
  • Removed the redundant destination-side "Files Cloned" workflow (4 → 2 workflow DB writes
    per cloned item). Clone provenance is retained via the source workflow + the preserved
    original-project field; rollback-on-failure is unchanged.

Security — parameterized listing query (#5 )

  • The subject/experiment listing SQL behind the transfer screen is fully parameterized
    (:userId, :project, :ids) via NamedParameterJdbcTemplate. Request-derived filter
    values are now bound parameters instead of being concatenated into the query string
    (SQL-injection hardening of the project/id filters).

UI fixes

Profiler analysis (Java Flight Recorder)

Profiling drove the conservative concurrency defaults and confirmed where time actually goes.

Clone is filesystem/metadata-bound. ~99% of clone time is filesystem work — hard-linking
(Files.createLink) and directory walks. The catalog-read optimization above removed a large
block of needless file opens; what remains is irreducible link + walk syscalls. More
parallelism does little, because the cost is shared-storage I/O, not CPU.

Reimport is bound by prearchive storage I/O and the anonymization pipeline (DICOM parse +
DicomEdit/mizer) — not CPU, and not plugin-level locking.

Conclusions baked into this PR:

  • Concurrency defaults are deliberately low (Reimport 4–8, Clone 1–2) and fully admin-tunable,
    with a min = max = 1 serial kill-switch.
  • The real throughput lever is prearchive storage, not consumer count. On slow or
    bind-mounted storage, keep concurrency at 1; raise it only on fast local/SAN storage. Captured
    in docs/ROADMAP.md under Performance & scaling.

Configuration & deployment notes

  • Version bumped to 1.0.1-RC; built for JDK 8 / XNAT 1.9.3.3.
  • Queue concurrency is set in Site Administration (Batch Transfer queue settings) or via
    /xapi/batch_transfer/jms_queues.

kelseym added 7 commits June 16, 2026 08:51
… select

- Reimport: suppress session expand arrows whose only children (image assessors)
  are out of scope, via a `bt-reimport-mode` body flag + CSS. Share/Clone unaffected.
- Re-query destination anon status on each selection (checkProjectAnon forceRefresh)
  instead of reading a page-load snapshot; drop the up-front bulk pre-fetch.
…OM strings.

Prepared CHANGELOG, ROADMAP and version for PR.
@kelseym kelseym requested a review from kathrynalpert June 22, 2026 21:02
@kelseym kelseym changed the title Batch Transfer 1.0.1-RC — parallel Share/Clone/Reimport, query hardening, UI fixes Batch Transfer 1.0.1-RC — parallel Clone/Reimport, query hardening, UI fixes Jun 22, 2026
@kelseym kelseym requested a review from ransfordj June 23, 2026 18:21
@kathrynalpert

kathrynalpert commented Jun 24, 2026

Copy link
Copy Markdown

I don't think you want to allow modifying JMS queue settings live / without tomcat restart (https://radiologics.atlassian.net/browse/CS-1037).

Edit: I see now that you require a tomcat restart, nevermind this concern!

@kelseym kelseym merged commit 276fb52 into main Jun 25, 2026
1 check passed
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.

3 participants