Skip to content

feat(fastq): UMI-in-read-name output and BAM→FASTQ on the typed-step chain - #482

Merged
nh13 merged 4 commits into
feat-runallfrom
480/nh/feat-umi-in-fastq-header
Jul 9, 2026
Merged

nh13 merged 4 commits into
feat-runallfrom
480/nh/feat-umi-in-fastq-header

Conversation

@nh13

@nh13 nh13 commented Jul 7, 2026 •

Copy link
Copy Markdown
Member

Reworks fgumi fastq to (a) emit UMIs in the read name in Illumina DRAGEN format and (b) run all BAM→FASTQ conversion — interleaved and paired split — through the typed-step pipeline chain, sharing one work-stealing compression pool.

Stacked on #476 (base nh/sort-6-chains-wiring). Do not merge before #476. Review this PR's own diff via the 4 commits below.

What's here (suggested reading order):

  1. b8aaa812 — UMI-in-read-name (--annotate-read-names/-U, --umi-tag, delimiters) matching samtools fastq -U DRAGEN output, plus paired -1/-2/-0 BGZF split.
  2. 899325db — route interleaved BAM→FASTQ through the chain (new WriteRawFile raw/BGZF sink).
  3. 3f5911c8 — new 3-output ordered pipeline primitive (OrderedBytesTuple3 + Process3WithWorkerState), the one-branch-wider analog of the existing Tuple2/Process2.
  4. cd12c109 — route paired --out1/--out2/--out0 through the chain via a 3-way fan-out; retire the standalone run_paired loop + FastqSink.

Why the chain: the old paired loop opened a separate pool of --threads BGZF workers per output (three .gz outputs at --threads N = 3N compression workers). On the chain the three per-file compressors share one pool, and RSS is bounded by the lean queue-memory default instead of growing per output.

Correctness: the paired encode emits a block on all three ordered branches for every input batch (empty where a branch has no records) — a skipped batch serial would wedge that branch's reorder stage; a deterministic unit test pins this. Paired output is byte-parity with samtools fastq -1/-2/-0 (asserted in-test); interleaved with samtools fastq -U.

Validation: full suite green; cargo ci-lint/ci-fmt clean; --no-default-features builds. tricorder on 4.2M records: 5.7× wall speedup at -@8, RSS bounded ~390 MB (flat -@4→-@8) vs ~6 GB under the old per-thread default.

Closes #480.

Summary by CodeRabbit

  • New Features

    • Added FASTQ output support in both interleaved and paired/split modes.
    • FASTQ read names can now include UMIs, with configurable tag priority and separators.
    • Added support for raw byte output and improved gzip/BGZF writing behavior.
  • Bug Fixes

    • Prevents FASTQ exports from overwriting the input or reusing the same output path.
    • Keeps paired FASTQ branch ordering stable, even when a branch has no records.
  • Documentation

    • Expanded guidance for UMI-annotated FASTQ workflows and updated command descriptions.

@nh13
nh13 temporarily deployed to github-actions July 7, 2026 21:31 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Jul 7, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 38 seconds

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 74bcd252-de5f-4383-a1da-ee38260f090b

📥 Commits

Reviewing files that changed from the base of the PR and between 6bbbaa1 and 062c149.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !**/*.lock
📒 Files selected for processing (24)
  • Cargo.toml
  • crates/fgumi-bam-io/src/grouping.rs
  • crates/fgumi-bam-io/src/lib.rs
  • crates/fgumi-bam-io/src/writer.rs
  • crates/fgumi-pipeline-core/src/handles.rs
  • crates/fgumi-pipeline-core/src/outputs.rs
  • crates/fgumi-pipeline-io/src/sink/mod.rs
  • crates/fgumi-pipeline-io/src/sink/write_raw.rs
  • docs/src/guide/best-practices.md
  • docs/src/index.md
  • src/lib/commands/fastq.rs
  • src/lib/commands/runall.rs
  • src/lib/pipeline/chains/builder.rs
  • src/lib/pipeline/chains/commands/fastq.rs
  • src/lib/pipeline/chains/commands/mod.rs
  • src/lib/pipeline/chains/options_bag.rs
  • src/lib/pipeline/chains/sink_spec.rs
  • src/lib/pipeline/chains/stage.rs
  • src/lib/pipeline/chains/validate.rs
  • src/lib/pipeline/steps/align_and_merge.rs
  • src/lib/pipeline/steps/process.rs
  • src/lib/pipeline/steps/sink/mod.rs
  • src/lib/pipeline/steps/sink/write_raw.rs
  • tests/integration/test_fastq_command.rs

Walkthrough

Adds FASTQ UMI-in-header output, new terminal FASTQ sink/stage wiring, raw-byte and 3-way pipeline support, and matching validation, tests, and docs.

Changes

FASTQ UMI output

Layer / File(s) Summary
UMI parsing and formatting
src/lib/commands/fastq.rs, src/lib/pipeline/steps/align_and_merge.rs
Adds UMI tag parsing, read-name formatting, and the explicit None UMI-header callsite needed by the updated FASTQ writer.
FASTQ stage and sink wiring
src/lib/commands/runall.rs, src/lib/pipeline/chains/*
Adds the Fastq stage and sink variants, validates terminal FASTQ placement, and routes FASTQ chain/sink execution through the new output path.
3-output and raw-byte pipeline support
Cargo.toml, crates/fgumi-bam-io/src/*, crates/fgumi-pipeline-core/src/*, crates/fgumi-pipeline-io/src/*, src/lib/pipeline/steps/*
Adds 3-way ordered process output, raw-byte sink support, and the BGZF writer helper used by compressed FASTQ output paths.
Tests and docs
src/lib/commands/fastq.rs, tests/integration/test_fastq_command.rs, docs/src/guide/best-practices.md, docs/src/index.md
Adds unit/integration coverage for UMI formatting, paired and gzipped output, CLI validation, and updates user-facing FASTQ docs.

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

Possibly related PRs

Suggested labels: enhancement

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR adds configurable UMI-in-header FASTQ output, paired R1/R2/BGZF support, and defaults RX/OX plus name/UMI delimiters as required.
Out of Scope Changes check ✅ Passed The added pipeline primitives, raw sink, and docs/test updates support the FASTQ objective rather than introducing unrelated behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: UMI-in-read-name FASTQ output and BAM→FASTQ conversion on the typed-step chain.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 480/nh/feat-umi-in-fastq-header

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

@codecov

codecov Bot commented Jul 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.23377% with 54 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (feat-runall@84dfccb). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/lib/pipeline/steps/process.rs 73.78% 43 Missing ⚠️
src/lib/commands/fastq.rs 95.80% 6 Missing ⚠️
src/lib/pipeline/chains/commands/fastq.rs 98.50% 3 Missing ⚠️
src/lib/pipeline/chains/sink_spec.rs 50.00% 1 Missing ⚠️
src/lib/pipeline/chains/validate.rs 96.42% 1 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff               @@
##             feat-runall     #482   +/-   ##
==============================================
  Coverage               ?   94.18%           
==============================================
  Files                  ?      111           
  Lines                  ?    50744           
  Branches               ?        0           
==============================================
  Hits                   ?    47794           
  Misses                 ?     2950           
  Partials               ?        0           

☔ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/commands/fastq.rs`:
- Around line 374-379: The UMI annotation block in fastq::write output uses
chained if let syntax that is not compatible with the pinned Rust 1.87.0 MSRV.
Update the logic in the umi_header/uh.lookup(record) path to use nested if let
statements in the fastq command code, or otherwise bump the workspace MSRV if
that syntax must stay.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 63f18774-067e-410d-ae50-250ee0ff8e98

📥 Commits

Reviewing files that changed from the base of the PR and between cdcd5a7 and 6ebeac1.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !**/*.lock
📒 Files selected for processing (3)
  • Cargo.toml
  • src/lib/commands/fastq.rs
  • tests/integration/test_fastq_command.rs

Comment thread src/lib/commands/fastq.rs
@nh13
nh13 force-pushed the 480/nh/feat-umi-in-fastq-header branch from 6ebeac1 to 7048cb9 Compare July 7, 2026 22:09
@nh13
nh13 temporarily deployed to github-actions July 7, 2026 22:09 — with GitHub Actions Inactive
@nh13 nh13 changed the title feat(fastq): embed UMI in read header (mirror samtools fastq -U) feat(fastq): UMI-in-read-name and paired BGZF split output for fgumi fastq Jul 7, 2026
@nh13

nh13 commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 7, 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 force-pushed the 480/nh/feat-umi-in-fastq-header branch from 7048cb9 to c51f771 Compare July 7, 2026 22:39
@nh13
nh13 temporarily deployed to github-actions July 7, 2026 22:39 — with GitHub Actions Inactive
@nh13
nh13 force-pushed the 480/nh/feat-umi-in-fastq-header branch from c51f771 to 02d4e32 Compare July 7, 2026 22:48
@nh13
nh13 temporarily deployed to github-actions July 7, 2026 22:48 — with GitHub Actions Inactive
@nh13

nh13 commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 7, 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/commands/fastq.rs`:
- Around line 394-481: The paired FASTQ path in run_paired currently hardcodes
no_suffix to true, so --out1/--out2 mode can never emit /1 and /2 suffixes.
Update the suffix selection logic in run_paired to respect self.no_suffix (or an
explicit always-suffix option) when calling write_fastq_record, so users can
choose samtools -N-equivalent behavior instead of always suppressing suffixes.
Keep the change localized around the no_suffix variable and the
write_fastq_record call in run_paired.
- Around line 109-206: The FASTQ output path handling can oversubscribe CPU
because FastqSink::open_file creates a full compression pool per compressed
sink, and run_paired may open out1/out2/out0 at once. Update the thread
allocation so compressed outputs either share/divide the requested threads
across all active sinks or, at minimum, log the effective total worker count
when opening multiple BGZF sinks. Use the existing FastqSink::open_file,
run_paired, and log_config symbols to wire this in.
- Around line 751-831: Several of the test functions in this block are
table-driven and should be converted from single `#[test]` cases into `rstest`
parameterized tests. Update `parse_umi_tags_rejects_malformed`, the
`umi_annotation_*` tests, `classify_segment_by_flags`, and
`gz_extension_is_detected` to use `#[rstest]` with `#[case(...)]` for each
input/output pair, keeping the existing assertions but splitting repeated
scenarios into cases. Use the existing helpers `parse_umi_tags`,
`UmiHeader::from_args`, `write_annotation`, `classify_segment`, and
`path_is_gzip` as the targets for the cases.
- Around line 493-510: The output-path validation in the fastq command only
checks each of `self.output`, `self.out1`, `self.out2`, and `self.out0` against
`self.input`; extend this check to also reject any duplicate output destinations
among those four paths. Use the same lexical/canonicalized path comparison
already present in that loop, but compare outputs pairwise or via a set of
canonical paths before opening any sinks, and raise the same `anyhow::bail!`
error when two output flags resolve to the same file.

In `@tests/integration/test_fastq_command.rs`:
- Around line 609-632: Strengthen test_fastq_interleaved_gz_is_bgzf so it
verifies the actual FASTQ records, not just that two records were produced. In
the test_fastq_interleaved_gz_is_bgzf body, after read_fastq_maybe_gz(&out),
assert the expected record names and sequences (and any mate ordering if
relevant), using the same kind of identity checks as
test_fastq_paired_output_is_bgzf. Keep the BGZF header checks, but replace the
weak recs.len() only assertion with explicit per-record validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6072f885-9169-4119-a1a7-30ba6a43aadf

📥 Commits

Reviewing files that changed from the base of the PR and between 6ebeac1 and 02d4e32.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !**/*.lock
📒 Files selected for processing (7)
  • Cargo.toml
  • crates/fgumi-bam-io/src/lib.rs
  • crates/fgumi-bam-io/src/writer.rs
  • docs/src/guide/best-practices.md
  • docs/src/index.md
  • src/lib/commands/fastq.rs
  • tests/integration/test_fastq_command.rs

Comment thread src/lib/commands/fastq.rs
Comment thread src/lib/commands/fastq.rs Outdated
Comment thread src/lib/commands/fastq.rs Outdated
Comment thread src/lib/commands/fastq.rs Outdated
Comment thread tests/integration/test_fastq_command.rs
@nh13

nh13 commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai On the -N/always-suffix point (fastq.rs:481): intentionally not adding a force-suffix flag. In split --out1/--out2 mode the /1 /2 suffix is omitted to match samtools fastq -1/-2 default behavior, which keeps R1/R2 names identical for downstream pairing — the correct convention here. No current use case needs -N-style forced suffixes in split files, so leaving it out (YAGNI); happy to add it if a concrete need arises.

On the per-output BGZF thread pools (fastq.rs:206): kept the undivided per-sink pools (benchmarked ~7% faster at low -@ than dividing the budget) and now log the effective total compression-worker count when multiple gzipped outputs are opened, so oversubscription is visible. A deeper fix — routing all FASTQ compression through the shared work-stealing pool via a typed-step FASTQ sink — is planned as a follow-up once the sort-engine stack lands.

@nh13
nh13 force-pushed the 480/nh/feat-umi-in-fastq-header branch from 02d4e32 to bc30a00 Compare July 8, 2026 00:43
@nh13
nh13 temporarily deployed to github-actions July 8, 2026 00:44 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@nh13 Understood on both points — makes sense.

  • Split-mode /1//2 omission matching samtools fastq -1/-2 convention for downstream pairing is reasonable; agreed YAGNI on a force-suffix flag until there's a concrete need.
  • Undivided per-sink BGZF pools with the new worker-count logging is a fine interim tradeoff given the benchmark data; the shared work-stealing pool via typed-step FASTQ sink sounds like the right long-term fix once the sort-engine work lands.

No further action needed from me here.


✏️ Learnings added
Learnt from: nh13
URL: https://github.com/fulcrumgenomics/fgumi/pull/482

Timestamp: 2026-07-08T00:44:16.638Z
Learning: Repo: fulcrumgenomics/fgumi. In `src/lib/commands/fastq.rs`, split `--out1`/`--out2` FASTQ output intentionally omits `/1`/`/2` read-name suffixes (even without an explicit force-suffix flag), to match `samtools fastq -1/-2` default behavior and keep R1/R2 names identical for downstream pairing. This is a deliberate design choice (YAGNI on adding a `-N`-style forced-suffix flag), not a bug.

Learnt from: nh13
URL: https://github.com/fulcrumgenomics/fgumi/pull/482

Timestamp: 2026-07-08T00:44:16.638Z
Learning: Repo: fulcrumgenomics/fgumi. In `src/lib/commands/fastq.rs`, BGZF compression thread pools are intentionally kept undivided per output sink (not split across multiple gzipped outputs), based on benchmarking showing ~7% better throughput at low `-@` thread counts vs. dividing the thread budget. The effective total compression-worker count is logged when multiple gzipped outputs are opened to surface oversubscription. Routing all FASTQ compression through a shared work-stealing pool via a typed-step FASTQ sink is a planned follow-up once the sort-engine stack lands.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@nh13

nh13 commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 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 commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 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 commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 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 commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/src/guide/best-practices.md`:
- Line 516: The section heading level is skipping too far under the existing
`##` parent, causing a heading-increment violation. Update the heading in this
part of `best-practices.md` to use the correct nested level (change the `####
Optional: Interleaved output and custom delimiters` heading to `###`), keeping
the section aligned with the surrounding markdown structure.

In `@src/lib/commands/fastq.rs`:
- Around line 520-548: The duplicate-output validation in fastq::Command::run
still misses equivalent paths when the target file does not exist yet because
canonical only resolves existing files; update that helper so it also normalizes
non-existent outputs by canonicalizing the parent directory and joining the
final component, then keep using it for both the input_key comparison and the
seen HashSet dedup in the output_paths loop. Preserve the /dev/null exception,
and use nested if let logic in canonical rather than a newer let-chain so the
fix stays compatible with the current MSRV.
- Around line 445-455: Reject aliased output paths in execute() before any
FastqSink::open_file calls by normalizing all requested outputs, including
non-existent ones, against the current working directory and comparing the
resolved paths for out1, out2, and out0. Update the path validation logic around
execute() so aliases like ./out.fq and out.fq are detected even when the files
do not yet exist, and fail early instead of allowing multiple sinks to open the
same target.

In `@tests/integration/test_fastq_command.rs`:
- Around line 518-524: The BGZF integration coverage is missing the `.bgz` path,
so a writer bug specific to that extension would not be caught. Add a
`.bgz`-suffixed variant of the existing `test_fastq_paired_output_is_bgzf` in
`test_fastq_command.rs` and use `read_fastq_maybe_gz` to validate it, so both
supported extensions are exercised. Keep the change focused on the FASTQ BGZF
test helpers and the paired-output test coverage.
- Around line 416-514: The UMI-in-header tests in test_fastq_command.rs only
verify fixed output strings, so add a parity check against the samtools fastq -U
formatting path for the annotating logic used by run_fastq_with_args and
--annotate-read-names. Keep the existing smoke tests, but introduce an
independent oracle for the formatting behavior so the duplex UMI annotation can
be validated without relying solely on hard-coded expected names, especially
around RX/OX selection and the UMI delimiter/separator handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: cf1d55b0-bf2b-4436-a6eb-dbae03f22663

📥 Commits

Reviewing files that changed from the base of the PR and between 02d4e32 and bc30a00.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !**/*.lock
📒 Files selected for processing (7)
  • Cargo.toml
  • crates/fgumi-bam-io/src/lib.rs
  • crates/fgumi-bam-io/src/writer.rs
  • docs/src/guide/best-practices.md
  • docs/src/index.md
  • src/lib/commands/fastq.rs
  • tests/integration/test_fastq_command.rs

Comment thread docs/src/guide/best-practices.md Outdated
Comment thread src/lib/commands/fastq.rs Outdated
Comment thread src/lib/commands/fastq.rs
Comment thread tests/integration/test_fastq_command.rs
Comment thread tests/integration/test_fastq_command.rs
@nh13
nh13 force-pushed the 480/nh/feat-umi-in-fastq-header branch from bc30a00 to cd12c10 Compare July 8, 2026 07:21
@coderabbitai

coderabbitai Bot commented Jul 9, 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 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 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 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 merged commit 665bcfc into feat-runall Jul 9, 2026
11 checks passed
@nh13
nh13 deleted the 480/nh/feat-umi-in-fastq-header branch July 9, 2026 21:03
nh13 added a commit that referenced this pull request Jul 12, 2026
#534)

* fix(fastq): use DecodedRecordBatch accessors instead of private-field destructure

The #482 fastq encode/paired steps destructured DecodedRecordBatch's now-private
batch_serial/records fields directly, breaking the workspace build after those
fields were made private to protect the cached total_bytes invariant. Capture the
serial via batch_serial() and take ownership via into_records() instead. Behavior
is unchanged; 117 fastq tests pass.

* fix(sort): fail closed on poisoned spill-reader mutex instead of hanging

Both spill-decompress fill paths (inline and block-parallel) acquired the
per-slot reader mutex with try_lock() and treated any Err identically as
'contended, skip'. A poisoned mutex — a fill worker that panicked mid-read —
was therefore swallowed as WouldBlock and the slot skipped forever: queue_eof
never got set, so SortMerge spun on Contention and deadlocked instead of
surfacing the panic. Distinguish the TryLockError variants: WouldBlock still
skips; Poisoned now marks the slot failed (decomp_error + queue_eof) and
returns Err so the failure propagates. Adds a regression test poisoning the
reader mutex on both paths.

* fix(align): latch consumer-gone on a reader-thread panic via RAII guard

The align-and-merge reader thread called gate.mark_consumer_gone() only after
reader_loop returned, so a panic in reader_loop skipped the latch: a writer
parked in InFlightGate::acquire never woke, and Drop's writer_thread.join()
hung the process with no surfaced error. Move the latch into a ConsumerGoneGuard
whose Drop fires on every exit including unwind. Adds a unit test asserting a
panic in the guarded scope still bails a blocked acquire().

* fix(align): drain aligner stderr byte-oriented so a non-UTF-8 line can't deadlock

relay_stderr used BufRead::lines() and broke the drain loop on the first Err,
which lines() yields for any non-UTF-8 line. Once draining stopped, the aligner
blocked writing to its stderr pipe as soon as it filled (~64 KiB), hanging the
whole align pipeline. Switch to read_until(b'\n') + from_utf8_lossy so invalid
UTF-8 is decoded, not fatal, and the relay always drains to EOF. Adds a
regression test feeding a non-UTF-8 line mid-stream.

* fix(duplex): validate min-reads before the pipeline is built to avoid a worker panic

The duplex per-worker init closure builds DuplexConsensusCaller with .expect(),
so an invalid --min-reads ordering (e.g. '1 5', total < XY) panicked inside a
worker thread on the threaded/runall path — likely wedging the pipeline —
whereas the single-threaded path errored cleanly. Extract the min-reads
validation out of DuplexConsensusCaller::new into a reusable
DuplexConsensusCaller::validate_min_reads, and call it up front in
ChainBuilder::add_duplex so every path surfaces a clean error before the
pipeline is constructed. Codec/simplex already guard this; duplex was the
outlier. Adds a unit test covering empty, >3 values, and both bad orderings.

This branch was previously deployed

1 inactive deployment
github-actions — 062c1496 Deployed Jul 8, 2026 by nh13 via coverage #2001
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.

feat(fastq): add UMI-in-read-header output to fgumi fastq (replace samtools fastq -U)

1 participant