Skip to content

feat(importer): make NZB compression configurable and number only on collision (#679)#687

Merged
javi11 merged 3 commits into
mainfrom
session/laughing-hermann-f4c754
Jun 15, 2026
Merged

feat(importer): make NZB compression configurable and number only on collision (#679)#687
javi11 merged 3 commits into
mainfrom
session/laughing-hermann-f4c754

Conversation

@javi11

@javi11 javi11 commented Jun 15, 2026

Copy link
Copy Markdown
Owner

What & why

Closes #679. Users reported that persisted NZBs were saved as numbered entries (1, 2, 3…) and only as gzip .nzb.gz, rather than as plain .nzb in their category folders (Movies, Series, corrupted, etc.). Two behaviors in internal/importer caused this:

  1. Forced numberingensurePersistentNzb always nested every successful NZB under a per-queue-ID subfolder .nzbs/{category}/{id}/. The {id} was the "number" users saw.
  2. Always gzip — every NZB was compressed to .nzb.gz, with a startup migration also rewriting any plain .nzb. There was no opt-out.

Changes

  • Configurable compression: new import.compress_nzb option (*bool, default true = unchanged behavior) with a ShouldCompressNzb() accessor. When disabled, NZBs are moved as plain .nzb (rename with copy+remove fallback) instead of gzip-compressed. The one-time gzip migration early-returns while compression is off so it won't rewrite plain files behind the user's back. Reads already tolerate both extensions via nzbfile.Open/ResolveOnDisk.
  • Number only on collision: NZBs now save directly to .nzbs/{category}/{name}{ext}. The per-ID disambiguation only kicks in when the destination is already taken, applied as an {id}-{name} filename prefix (kept in the category folder), mirroring the existing failed-path convention (uniqueFailedNzbPath). The collision check is both disk- and DB-aware so the UNIQUE import_queue.nzb_path constraint still holds even after DeleteCompletedNzb removes a file. Extracted into a testable persistentNzbPath helper.
  • End-to-end wiring: Go config struct + default + accessor, ImportAPIResponse field + mapping, frontend ImportConfig/ImportUpdateRequest types, and a "Compress Stored NZBs" toggle in WorkersConfigSection.tsx.

The failed path (.nzbs/failed/{category}/) already numbered only on collision and needed no change.

Reviewer notes

  • Default is compress_nzb: true, so existing installs are unaffected; users opt into plain .nzb.
  • The {id}- filename prefix on collision is a deliberate choice (per request) consistent with the failed-folder behavior.

Testing

  • New TestPersistentNzbPath covers free-destination (clean name) and collision (prefixed) cases for both extensions.
  • go test -race ./internal/importer/... ./internal/config/... ./internal/api/... and go vet pass.
  • Frontend bun run check (biome) passes.

javi11 added 3 commits June 15, 2026 09:07
…collision (#679)

Persisted NZBs were always stored gzip-compressed (.nzb.gz) and always
nested under a per-queue-ID subfolder (.nzbs/{category}/{id}/), which
surfaced to users as files numbered 1, 2, 3 inside their category folders.

- Add `import.compress_nzb` config option (default true = unchanged). When
  disabled, NZBs are kept as plain .nzb in their category folders. The
  one-time gzip migration is skipped while compression is off so it does
  not rewrite plain files. Reads already tolerate both extensions.
- Drop the forced per-ID subfolder: save directly to
  .nzbs/{category}/{name}{ext} and only namespace with an `{id}-` filename
  prefix on collision (DB- and disk-aware), mirroring the failed-path
  convention.
- Wire the option end-to-end: Go config + accessor, API response type,
  frontend ImportConfig types, and a "Compress Stored NZBs" toggle.

Closes #679
On a failed rename (e.g. cross-device), leave the source NZB untouched and
return an error so the import can retry, rather than risking a partial copy.
Removes the now-unused copyFile fallback.
Mirror the existing nzbfile.GzExtension constant instead of a hardcoded
".nzb" literal in ensurePersistentNzb, centralizing NZB extension knowledge.
@javi11 javi11 merged commit fe60edc into main Jun 15, 2026
2 checks passed
@javi11 javi11 deleted the session/laughing-hermann-f4c754 branch June 15, 2026 07:54
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.

Saving downloaded nzbs as non tar

1 participant