Skip to content

feat(retag): add --threads and route through the unified pipeline - #871

Merged
nh13 merged 1 commit into
mainfrom
nh/retag-threads
Aug 28, 2026
Merged

nh13 merged 1 commit into
mainfrom
nh/retag-threads

Conversation

@nh13

@nh13 nh13 commented Aug 27, 2026 •

Copy link
Copy Markdown
Member

What

Adds --threads N to fgumi retag and routes it through the existing unified 7-step BAM pipeline, matching how filter and clip already work. Without --threads, the original single-threaded serial loop runs unchanged.

retag is a pure per-record SAM aux-tag rewriter (copy/move/delete ops applied left-to-right). It previously hardcoded a 1-reader / 1-writer serial loop with no way to opt into parallelism, while every other BAM-processing command exposed --threads.

How

  • execute() keeps all up-front guards (io.validate, output-collision, input-aliasing via canonicalize, and now log_effective_check_crc) before the mode branch, so both paths enforce them identically.
  • No --threads → the serial loop, extracted verbatim into run_single_threaded.
  • --threads N → run_threaded, using SingleRawRecordGrouper (one record per group — retag needs no template batching) and applying the ops in the pipeline's process_fn.
  • Per-operation OpCounts are u64 counters accumulated into a PerThreadAccumulator<Vec<OpCounts>> and summed after the pipeline drains. Because addition is commutative and the counters are u64, the aggregated counts — and the --metrics TSV — are identical between serial and threaded modes at any thread count.
  • --metrics deliberately keeps working under --threads (unlike clip, whose per-read metrics are not summable and are rejected under --threads).
  • Sets group_key_config to the raw-no-cell config to skip a per-record cell-barcode scan.

The flattened ThreadingOptions / SchedulerOptions / QueueMemoryOptions (i.e. --threads, --scheduler, --max-memory/--memory-reserve/--memory-per-thread) mirror filter/clip. --compression-level and the CRC/async flags already existed.

Also a small drive-by fix: retag now calls log_effective_check_crc(), finally emitting the per-run CRC verify: line its --check-crc doc already promised.

Correctness

Output order is preserved by the pipeline, so threaded output matches serial record-for-record. Verified via the real binary (serial vs --threads 4): decoded records + --metrics TSV byte-identical; output headers differ only in the @PG CL: field (which correctly records the different argv); --compression-level honored in threaded mode; the zero-match warning fires in threaded mode; --threads 0 is rejected cleanly.

Tests

All in retag.rs:

  • threaded_output_matches_single_threaded (--threads 1 and --threads 4): asserts decoded-record equality, header equality, and byte-identical --metrics TSV against the serial path, over a 50-record corpus spanning the classes where a decode divergence could hide — mapped/paired reads with real CIGAR + MC/RG tags (some secondary), records that pre-carry BX so dst_overwritten is exercised, and a zero-match delete.
  • threaded_preserves_input_record_order (--threads 4).
  • threads_flag_coexists_with_positional_operations (clap parse: --threads alongside the positional SRC::op::DST args).

cargo ci-test, cargo ci-fmt, cargo ci-lint all pass.

Risk: output changes for threaded retag, pinned by serial-equivalent metrics, ordering, validation, and compression tests; unsafe changes: none; memory and thread policy changes: --threads, scheduler, and queue-memory options add bounded threaded execution.

Fix: use the threaded path only when --threads is set. Keep the existing serial path unchanged.

  • Add --threads N to fgumi retag.
  • Route threaded execution through the unified seven-step BAM pipeline.
  • Preserve output order and aggregate per-operation u64 counts.
  • Apply validation and collision checks in both execution modes.
  • Skip unnecessary cell-barcode scanning.
  • Log effective CRC verification settings at execution start.
  • Add tests for output and metrics equivalence, ordering, positional operation parsing, compression, warnings, count aggregation, and invalid thread counts.
  • CI tests, formatting, and linting pass.

@nh13
nh13 deployed to github-actions August 27, 2026 01:08 — with GitHub Actions Active
@coderabbitai

coderabbitai Bot commented Aug 27, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 72a36835-36a5-4442-bb3b-0d2f82df24f2

📥 Commits

Reviewing files that changed from the base of the PR and between a927ef0 and 026267c.

📒 Files selected for processing (1)
  • src/lib/commands/retag.rs

Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour.


Walkthrough

Risk: threaded execution can alter record ordering, headers, and metric aggregation. Fix: select serial or unified pipeline execution and validate parity with threaded tests.

Changes

Retag threading

Layer / File(s) Summary
Retag execution configuration
src/lib/commands/retag.rs
Retag now includes threading, scheduler, and queue-memory options. Serial execution returns shared record and operation counts.
Serial and threaded execution
src/lib/commands/retag.rs
Execution logs the CRC policy, selects the path from --threads, processes operations in workers, preserves input order, and aggregates per-thread counts.
Command wiring and parity validation
src/lib/commands/retag.rs
Command builders initialize pipeline options. Tests compare serial and threaded records, headers, metrics, ordering, CLI parsing, and count aggregation.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to 02626

The change adds optional threaded execution while preserving the existing serial behavior and reports targeted validation for output, metrics, ordering, compression, warnings, and invalid thread counts. No actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant Retag
  participant BAMReader
  participant PipelineWorkers
  participant BAMWriter
  participant Metrics
  Retag->>BAMReader: read grouped records
  BAMReader->>PipelineWorkers: submit raw records
  PipelineWorkers->>PipelineWorkers: apply retag operations and aggregate counts
  PipelineWorkers->>BAMWriter: emit records in input order
  Retag->>Metrics: report record totals and operation counts
Loading
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required Conventional Commit format and accurately describes the main retag threading and unified-pipeline changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@nh13

nh13 commented Aug 27, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai pause

@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews paused.

@codecov

codecov Bot commented Aug 27, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.64253% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.68%. Comparing base (a927ef0) to head (026267c).

Files with missing lines Patch % Lines
src/lib/commands/retag.rs 98.64% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #871      +/-   ##
==========================================
- Coverage   94.69%   94.68%   -0.01%     
==========================================
  Files         194      194              
  Lines      119898   120103     +205     
==========================================
+ Hits       113532   113720     +188     
- Misses       6366     6383      +17     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

retag was single-threaded with a hardcoded 1 reader / 1 writer serial
loop. Add --threads N to route records through the unified 7-step
pipeline, matching filter and clip, along with the --scheduler and
--max-memory/--memory-reserve/--memory-per-thread knobs that ride with
it. Without --threads the original serial fast path is unchanged.

retag is a pure per-record transform, so the pipeline path uses
SingleRawRecordGrouper (one record per unit, no template batching) and
applies the ops in process_fn. Per-operation counts accumulate into a
PerThreadAccumulator and are summed after the pipeline drains; because
OpCounts are u64 and addition is commutative, the aggregated counts and
the --metrics TSV are identical to the serial path at any thread count.
This keeps --metrics available under --threads (a deliberate divergence
from clip, whose per-read metrics are not summable).

Also set group_key_config to the raw-no-cell config to skip a wasted
per-record cell-barcode scan, and call log_effective_check_crc() so
retag finally emits the per-run 'CRC verify:' line its --check-crc doc
already promised.

Output order is preserved by the pipeline, so threaded output matches
serial record-for-record.
@nh13
nh13 force-pushed the nh/retag-threads branch from 92e8ff8 to 026267c Compare August 27, 2026 01:28
@nh13
nh13 deployed to github-actions August 27, 2026 01:29 — with GitHub Actions Active
@nh13

nh13 commented Aug 27, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13
nh13 added this pull request to the merge queue Aug 28, 2026
Merged via the queue into main with commit c88f81d Aug 28, 2026
16 checks passed
@nh13
nh13 deleted the nh/retag-threads branch August 28, 2026 01:10
@nh13 nh13 mentioned this pull request Aug 28, 2026

This branch was successfully deployed

1 active deployment
github-actions — 026267c0 Deployed Aug 27, 2026 by nh13 via coverage #3938
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