Feat: NZB Preloading & Failed NZB Management#725
Feat: NZB Preloading & Failed NZB Management#725docloulou wants to merge 8 commits intoViren070:mainfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughA new NZB preloading feature is introduced across the entire stack. It adds user preference storage for preload configuration, defines a debrid service interface method, implements preloading logic in multiple services with concurrent request tracking and WebDAV polling, orchestrates asynchronous preloading within the main stream resolution flow, and provides UI controls for enabling and configuring preload behaviour. Changes
Sequence DiagramsequenceDiagram
actor User
participant UI as Frontend UI
participant Main as getStreams (Main)
participant Orchestrator as _preloadNzbs
participant Services as Debrid Services
participant WebDAV as WebDAV Storage
User->>UI: Enable preload & configure
UI->>Main: Call getStreams()
Main->>Main: Prepare stream response
Main->>Orchestrator: Fire _preloadNzbs(streams, context)
Note over Orchestrator: Async (fire-and-forget)
Orchestrator->>Orchestrator: Select top NZB streams
Orchestrator->>Orchestrator: Encode credentials per service
loop For each stream
Orchestrator->>Services: preloadNzb(url, category, folderName)
Services->>Services: Check existing downloads
alt Already exists
Services->>Orchestrator: Skip (log)
else Not present
Services->>Services: Call addNzb()
Services->>WebDAV: Poll for content
WebDAV-->>Services: Content appears/timeout
Services->>Orchestrator: Success/error (logged)
end
end
Orchestrator-->>Main: Complete (gracefully)
Main-->>User: Return streams
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@packages/core/src/debrid/usenet-stream-base.ts`:
- Around line 430-431: The static Set UsenetStreamService.preloadingUrls
currently stores raw NZB URLs globally causing cross-service waits and unbounded
growth; change keys to be service-scoped (e.g., combine service identifier with
the NZB URL into a preloadKey used wherever preloadingUrls is referenced),
remove entries when content already exists and immediately after a successful
resolve (delete preloadKey in the branches handling "content already exists" and
after "contentPath confirmed"), and implement a TTL cleanup (store timestamps or
use a Map<preloadKey, timestamp> and periodically purge entries older than the
TTL) to handle preloads that never resolve; update all usages of preloadingUrls
(including in addUrl and resolve code paths mentioned around
UsenetStreamService.preloadingUrls and lines ~600–625 and ~942–1001) to use the
new scoped key logic and removal behavior.
- Around line 627-632: The debug log in serviceLogger.debug is leaking raw NZB
URLs (nzbUrl) which may contain API keys; replace the raw nzbUrl with a masked
version before logging—e.g., call an existing masking helper (maskNzbUrl or
similar) to produce maskedNzbUrl = maskNzbUrl(nzbUrl) (or implement a small
maskUrl helper that strips query params/credentials) and use maskedNzbUrl in the
Preloaded NZB debug call while keeping category, expectedFolderName, and nzoId
unchanged.
In `@packages/core/src/main.ts`:
- Around line 2493-2509: The folder name is being derived from stream.url which
can be a proxied download URL; for NZB-type streams use stream.nzbUrl (falling
back to stream.filename) so the preload folder matches getExpectedFolderName()
used during resolve; update the logic around folderName (the block that
currently reads stream.url and sets folderName) to prefer stream.nzbUrl when
stream.type indicates an NZB (or when stream.nzbUrl exists), still URL-decode
the last path segment like decodeURIComponent(new
URL(...).pathname.split('/').pop()), and keep the existing fallback to
stream.filename ?? 'unknown_nzb'.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/core/src/debrid/torbox.ts`:
- Around line 598-618: The logged nzbUrl in the TorBox preload path may contain
indexer API keys; update the calls that log nzbUrl (the logger.debug in the "NZB
already exists" branch, the catch branch, and the success log after await
this.addNzb) to use a redacted version instead of the raw URL: implement a small
helper (e.g., maskNzbUrl or redactNzbUrl) that strips or masks sensitive query
params (like api_key, apikey, key, token) or otherwise replaces the query string
with a placeholder, and pass that masked value into the logger.debug metadata
(while leaving nzbUrl unchanged for actual operations such as this.addNzb).
|
Ready to be reviewed @Viren070 |
Added functionality to preload NZBs to NzbDAV/Altmount services based on user settings. This includes a new preloadNzb option in user data schema, UI settings for enabling/disabling the feature, and logic to handle the preloading process in the AIOStreams class. Updated relevant debrid services to support the new preload operation.
Updated the NZB processing logic to include an option for filtering out failed NZBs based on user-defined settings. This change introduces a new `filterFailedNzbs` property in the service schema and updates the relevant components to respect this setting, improving the overall user experience by preventing failed NZBs from cluttering the results.
Enhanced the folder name determination logic in the AIOStreams class to align with the expected behavior of NzbDAV and Altmount services. The update introduces the use of `path.basename()` for extracting the filename from NZB URLs, ensuring consistency in folder naming during the resolution process.
Updated the preloading URL tracking mechanism in the UsenetStreamService to include the service name in the key. This change ensures that concurrent access detection is scoped per service, improving the accuracy of the preloading process. Adjusted related logic to maintain consistency in URL management during preloading and content resolution.
Enhanced the NZB preloading feature to support the TorBox service alongside NzbDAV and Altmount. Updated the AIOStreams class to accommodate user-selected addons for preloading, allowing for more granular control over which NZBs are sent to the services. Additionally, modified the user data schema to include an optional addons array and updated the UI to reflect these changes.
Updated the logging functionality in both TorboxDebridService and UsenetStreamService to mask sensitive NZB URLs before logging. This enhancement improves security by preventing sensitive data exposure in logs while maintaining debug information integrity.
e39642a to
3a46cd1
Compare
Updated the NZB preloading functionality to support a new per-resolution mode, allowing users to specify the number of NZBs to preload for each resolution. This includes modifications to the user data schema to accommodate per-resolution counts, as well as UI updates for selecting and managing these settings. The AIOStreams class logic has been adjusted to handle the new mode, improving the flexibility of NZB preloading based on user preferences.
NZB Preloading & Failed NZB Management
🎯 Overview
This PR introduces three major improvements for Usenet streaming services (NzbDAV/Altmount/Torbox):
✨ Features
1. NZB Preloading
Global Settings (Miscellaneous)
Per-Addon Control (Newznab Settings)
How it works:
addUrl()in the background2. Smart Conflict Resolution
Problem Solved:
When a user clicks on a stream that's currently being preloaded,
addUrl()would fail with an internal server error (duplicate NZB).Solution:
addUrl()fails during resolve and the NZB is in the preload tracker:3. Failed NZB Management
Problem Solved:
NZBs that failed in SABnzbd without creating a WebDAV folder were not properly detected, appearing in results even though they're unavailable.
Solution:
listNzbs()now includes failed entries from SABnzbd history even without WebDAV folders📁 Modified Files
Core (
packages/core/src/)db/schemas.tspreloadNzbtoUserDataSchemaChanged
ServiceSchema.credentialsfromz.string()toz.any()debrid/base.tspreloadNzb()method toDebridServiceinterfacedebrid/usenet-stream-base.tspreloadNzb()with WebDAV check +addUrl()• Added preload tracking (
preloadingUrlsSet)• Conflict resolution: WebDAV polling on
addUrlfailure• Fixed
listNzbs()to include failed SABnzbd entriesdebrid/utils.tsfilterFailedNzbs?: booleantoBuiltinDebridServicesmain.ts_preloadNzbs()fire-and-forget pipeline• Filters by
addon.preset.options.preloadNzb === true• Runs after
_processStreamsviasetImmediatepresets/newznab.tspresets/builtin.tsgetBaseConfig()to passfilterFailedNzbsfrom service credentialsbuiltins/utils/debrid.tsservice.filterFailedNzbsutils/constants.tsFrontend (
packages/frontend/src/)components/menu/miscellaneous.tsxcomponents/menu/services.tsx🔧 Configuration
For End Users
Step 1: Enable Global Preloading
Step 2: Enable Per-Indexer
Step 3: Configure Failed NZB Filtering (Optional)
For Developers
Preload Flow:
Resolve Flow (with preload conflict):
🧪 Testing
only tested with NZBDAV
Test Preloading
Preloaded NZBentriesTest Conflict Resolution
Test Failed NZB Filtering
🐛 Known Limitations
🔄 Breaking Changes
None. All features are opt-in and backward compatible:
ServiceSchema.credentialsnow accepts any type (was string-only) but remains compatible📊 Performance Impact
listNzbs()(already cached)🙏 Acknowledgments
This feature addresses the long-standing issue of slow usenet stream startup times by proactively downloading the most likely streams. The conflict resolution ensures a smooth user experience even when clicking quickly.
Ready to merge ✅
Summary by CodeRabbit
New Features