Conversation
…roperty source Introduces a @ConfigProperty annotation that flags properties as user-configurable, combined with a DatabasePropertySource that lets runtime overrides persist to postgres and refresh Spring beans without a restart. Includes: - @ConfigProperty annotations + advanced flag + property type metadata - File browser API behind the config API - Per-provider test / verification endpoints - Migration of application.properties to YAML - Conversion of @ConfigurationProperties from data class to mutable class - spring-cloud-context for runtime rebinding - Removal of @ConditionalOnExpression from debrid client beans Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lback Migrates the NNTP config from a flat single-server shape to a pools list, each with host/port/credentials/TLS/maxConnections and a priority for fill/fallback. Adds CRUD endpoints for pools plus a test endpoint, and plumbs runtime updates through so pool changes applied via the config API take effect without a restart. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a JWT-based authentication layer that can protect the API and the qBittorrent / SABnzbd / actuator endpoints behind opt-in flags. Also generates short-lived tokens for temporary file access (used by the frontend file browser). Excludes Spring's default UserDetailsService auto-config so the generated-password warning no longer appears at startup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extracts NZB import tracking into a dedicated NzbImportRecord entity so the import pipeline can be observed and paginated. Adds a sortable/searchable /api/v1/imports history endpoint, exposes the current queue status with an ARTICLES_MISSING terminal state, and bumps nzb-streamer through 0.7.0 → 0.7.3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bundles several small fixes surfaced via glitchtip / observability: - Premiumize returning errors inside 200 responses now parses cleanly - Wrapped ClientAbortException no longer escalates to ERROR - ObjectOptimisticLockingFailureException on concurrent updates - DataIntegrityViolationException on duplicate-key conflicts - EOFException on abruptly closed streams Plus housekeeping: - Downgrade ktor from 3.5.0-eap-1584 to stable 3.4.1 - Extract FileController.detail() into focused private methods - Suppress noisy detekt warnings across the codebase Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two related fixes to how runtime config overrides take effect: - NNTP pools now re-sync with NzbStreamer after DB overrides are loaded on startup (previously pools stored in overrides were ignored until the next save) - HttpClient connect-timeout now reads the current config at request time instead of at bean creation, so overrides actually apply Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a file moves in the Arr, the queue response used to return stale paths cached at enqueue time. Resolves paths lazily via a dedicated endpoint that queries db_item directly, so queue responses always reflect the current on-disk layout. Also derives SABnzbd history storage path from the actual file location and tightens a few test isolation issues the changes surfaced. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a full health-check and repair pipeline for torrents on top of PGMQ: periodic re-verification of cached links, short-circuit on the first healthy debrid provider, and automatic Arr-side blocklist + search on failure. Migrates the health check surface to a dedicated REST API, adds scheduled PGMQ archive cleanup, and retires ARTICLES_MISSING in favour of a single FAILED terminal state. Bumps nzb-streamer to 0.7.4. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Improves Real-Debrid integration reliability around link-not-found / stale-link scenarios and sync consistency. Adds reference CLAUDE.md sections documenting both the Real-Debrid and NNTP/Usenet integrations so future work has a contentful starting point. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously WebDAV was mounted at the root, which meant any non-API path had to be disambiguated between WebDAV and the Spring MVC controllers. Moving it under /webdav cleanly separates the WebDAV surface from REST / static resources. BREAKING CHANGE: WebDAV clients (rclone, media servers) must update their URL from / to /webdav. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
debridav-frontend is now tracked as a git submodule and its built `dist/` gets copied into Spring Boot's static resources at build time. Users no longer need to deploy the frontend as a separate container — a single jib-built image serves both the API and the UI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the ad-hoc example/ with a curated docker-compose example that layers a minimal stack, an arrs override, and a full monitoring override (Prometheus + Grafana + dashboards + scraparr for Sonarr/Radarr metrics + postgres-exporter). Includes: - Security scope section in the example README - Rclone and NNTP dashboards ported from debridav-ci - Dracula palette for threshold colors, NNTP streams panel, platform tidy-up - Iterative compose fixes (network labels, healthcheck, Grafana iframe embedding, rclone AppArmor/userns/mount defaults, scraparr image) - UI feature-flag endpoint for the frontend to branch on - Runtime NNTP pool empty-list + blank-host handling - NNTP treated as implicitly enabled when any pool is configured; NNTP_ENABLED env var dropped Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
debridav now pushes VFS cache invalidation to rclone via its RC API whenever files are created / moved / deleted. This means the mounted filesystem picks up changes without waiting for rclone's dir-cache-time to expire, so a 2-minute dir-cache becomes safe. DatabaseFileService emits FileSystemChangedEvent, the rclone RC invalidator consumes it, refreshes all ancestor dirs (so new subdirs become visible), and omits the special dir name when refreshing the VFS root. Bumps debridav-frontend to 12d9b4c. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds an overview page that surfaces live activity without requiring the Grafana stack, powered by a new /api/v1/summary endpoint: - active streams with per-file bitrate + source - library file counts by source - import / health-check queue depths - basic CPU + memory Also migrates StreamingService and LibraryMetricsService from the Prometheus native client to Micrometer, and bridges Metrics.globalRegistry to Spring's MeterRegistry so meters registered by libraries that reach for the static registry (notably nzb-streamer) are visible via both the summary endpoint and /actuator/prometheus. Other odds and ends: - Auto-generate a random JWT key when none is configured (with a warning that tokens won't survive restarts) - Expose the backend version via /api/v1/ui-config - Dashboards updated to use the new nzb_streams_bitrate gauge Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Real-Debrid now skips the scheduled torrent sync unless REAL_DEBRID is in debrid-clients and an API key is set. Premiumize drops its init-time requirement that an API key be present so the bean can be created when the provider is disabled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Keys.hmacShaKeyFor (per RFC 7518 §3.2) requires HS256 keys to be ≥ 32 bytes and throws WeakKeyException otherwise. Previously only isBlank() was checked at startup and the key was built lazily, so a short secret like DEBRIDAV_AUTH_JWT_SECRET=mypassword passed boot and then caused HTTP 500 on /api/v1/auth/login (WeakKeyException escapes generateToken) plus silent 401s on every protected endpoint (WeakKeyException is a JwtException subtype, swallowed by the validator's catch). No log line pointed at the cause. Adds a @PostConstruct validator that fails fast with a clear message and the openssl command to generate a compliant secret. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…onsumer Previously PgmqConsumer's catch block only logged on failure — the message was never archived and read_ct was never inspected. Poisoned messages (malformed JSON, schema drift, deterministic handler failures) got redelivered every visibility-timeout and pinned workers forever. This commit: - Archives immediately on JsonProcessingException (retry can't fix a deserialization error). - For any other exception, compares entry.readCounter against a new pgmq.max-read-count config (default 5). If exhausted, dead-letters; otherwise lets the message redeliver for another attempt. - Dead-lettering wraps the original payload plus failure metadata (failureClass, failureMessage, readCount, enqueued/failed timestamps) into an envelope sent to <queueName>_dlq, then archives from the main queue so a worker slot is freed. - V20__create_pgmq_dlq_queues.sql provisions the five DLQs alongside the existing main queues. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Brings in the mobile fix for the repair history table — shows the Result column on narrow viewports (was previously hidden in favour of the less useful Reads column). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the static DEBRIDAV_UI_GRAFANA_DASHBOARDS_* env wiring in favour of runtime discovery: GrafanaDashboardService queries Grafana's /api/search?type=dash-db, filters to the `debridav` folder, and returns title + url pairs. New endpoint /api/v1/grafana/dashboards surfaces that list to the frontend. Auth: anonymous if Grafana allows it (the example stack does), otherwise set debridav.ui.grafana.api-key / DEBRIDAV_UI_GRAFANA_APIKEY. Organise a dashboard under Grafana's `debridav` folder and it shows up as a tab on next page load — no redeploy needed. Bumps debridav-frontend to 8de2824. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mobile fix: horizontally scroll Grafana dashboard tabs when the row is wider than the viewport (previously clipped off-screen). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spring MVC bridges suspend functions via kotlinx-coroutines-reactor's Mono adapter, which isn't on the classpath, so the call failed with NoClassDefFoundError: kotlinx/coroutines/reactor/MonoKt at runtime (500 on every dashboard fetch). The endpoint is infrequent and cheap, so wrapping the suspend call in runBlocking is simpler than pulling in coroutines-reactor just for this one bridge. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a Logs page to the frontend that tails /actuator/logfile via Range headers, plus a FrontendRoutingConfiguration that forwards the SPA's client-side routes to /index.html so deep links resolve on hard refresh. Backend exposes a file appender + the logfile endpoint. Housekeeping in the same push: - Removes the long-unused FileSystemImportService + debridav.root-path (plus its V1 tables via V19__drop_import_registry.sql) - Consolidates health-check/repair settings under a single health-check.* config group (replaces debridav.torrent-health-check-*, nntp.health-check-*, and repair.enabled) - Hard-codes the NNTP forward-threshold-bytes constant inside nzb-streamer; exposes read-ahead-segments as a @ConfigProperty - Rclone dir-cache-time bumped to 120s now that cache invalidation is pushed; DEBRIDAV_UI_GRAFANA_BASEURL made opt-in - Bumps debridav-frontend to e054619 (Logs page + Health settings tab) BREAKING CHANGE: debridav.root-path and related keys are gone; repair.enabled → health-check.repair-enabled; nntp.forward-threshold-bytes removed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Was pinned to a commit SHA (af14aba) that got squashed out of nzb-streamer's history. v0.8.0 is the properly-tagged release containing the same changes — plus the ref-counted bitrate gauge fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extract magic numbers, drop unused parameters, suppress TooManyFunctions on the cohesive DatabaseFileService, fold StreamingService.streamContents' catch chain into a helper, and tighten up minor style issues so :detekt passes and the test phase can run. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SabNzbdService now picks the easynews-by-name path when the easynews debrid client is enabled and no NNTP pool is configured, and falls through to the async PGMQ import path otherwise. This restores the behaviour easynews-only users expect — the addfile call is synchronous and doesn't try to parse the NZB body. Test wiring follows: TestContextInitializer no longer pre-populates nntp.pools, NZB-path tests opt in via the new @MockServerNntpTest meta- annotation (which adds NntpPoolInitializer alongside the existing one), and the duplicated waitForCompletion polling loops fold into a shared Awaitility-based awaitSabImportCompletion helper. The /webdav/ prefix gets applied across the integration tests that hit WebDAV directly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The fk_nzb_contents_document constraint was ON DELETE NO ACTION, so any attempt to delete an NzbDocument required callers to manually unlink the contents first. That made cleanup brittle in production and broke integration-test teardown in three ITs. Migration V21 swaps the constraint to ON DELETE CASCADE, and the matching @onDelete annotation keeps Hibernate's DDL generation in agreement. Also bump the test postgres container's max_connections to 300 — with ~12 cached @SpringBootTest contexts each holding a Hikari pool, the default 100 limit was exhausted and randomly broke whichever context loaded last. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
getStreamableLink returned the DB-cached download URL without checking that it was still alive — once Real-Debrid expired or rotated a link, we kept handing it out and streams failed with HTTP errors instead of recovering. The unrestrict-on-dead-link path was only ever reached when no DB record existed at all. Now: HEAD the cached download URL; if RD has retired it, delete the stale RealDebridDownloadEntity (locally and from the RD account) and re-unrestrict the share link to mint a fresh download. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Most of these were carried over from the audit memory. None changes behaviour today, but each removes a foot-gun that would surface as LazyInitializationException, dangling transactions, or surprising collection equality once the codebase grows. - Switch @onetomany on Torrent.files and UsenetDownload.debridFiles from EAGER to LAZY. The collection is loaded only when callers ask for it. The qBittorrent /api/v2/torrents/files endpoint now goes through a new TorrentService.getTorrentFilesByHash that initializes the collection inside a read-only transaction. - Drop @transactional from suspend fun getChildren — Spring binds the transaction to a thread, so it was a no-op for a function that resumes on a different thread anyway. - Drop @transactional from the UsenetRepository interface and put it back on the specific write-derived methods that actually need it. The interface-level annotation wrapped reads in unnecessary transactions. - Add business-key equals/hashCode to Torrent, UsenetDownload, Category, and DbDirectory so they survive Hibernate-proxy comparison and Set/Map membership. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A second pass on audit items: - Drop CascadeType.ALL from RemotelyCachedEntity.contents, LocalEntity.blob, and RealDebridTorrentEntity.files in favour of PERSIST + MERGE + REMOVE. The omitted REFRESH and DETACH paths were the audit's actual concern; lifecycle cascade is what we want. - Bound SabNzbdService.history(): the unconditional findAll() returned every UsenetDownload ever, which would OOM as the table grows. The per-category branch was just as unbounded. Both now use PageRequest.of(0, 500) and sort newest-first. - Add idx_db_item_directory_id, idx_torrent_category_id, and idx_usenet_download_category_id via migration V22, plus matching @Index annotations on the entities. Postgres does not auto-index FK columns, so deletes against the parent and joins against the child were doing sequential scans. - Drop the entity_copy_observer=allow override from application.yaml — Hibernate's safety check belongs on by default. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mobile fix for the NNTP pool editor header — stacks the name above the Test/Remove buttons on narrow viewports and truncates long hostnames instead of overflowing the card.
The published rapidyenc-kotlin-wrapper jar (v0.1.3 on jitpack) only bundles linux-x86-64/librapidyenc.so, so the arm64 layer of our multi-platform Docker image had no native binary to load. Wiring the local wrapper as an includeBuild lets us bundle linux-aarch64/ alongside linux-x86-64/ without waiting on a wrapper release. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
RateLimiterRegistry.ofDefaults() doesn't wire metrics automatically, so resilience4j_ratelimiter_available_permissions and _waiting_threads weren't being exposed — the 'Rate limiters' panel on the platform dashboard went empty. Pulls in resilience4j-micrometer and calls TaggedRateLimiterMetrics.bindTo (same for retries). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
rapidyenc-kotlin-wrapper v0.2.0 ships both linux-x86-64 and linux-aarch64 binaries, so the local-source workaround is no longer needed. ktor-nntp-client v0.5.0 already pulls the new version through its libs.versions.toml.
Pulls in ktor-nntp-client v0.5.1 and rapidyenc-kotlin-wrapper v0.2.0, the latter of which now bundles linux-aarch64/librapidyenc.so so multi-arch container images work without local-build overrides.
The /webdav/ URL prefix tipped these two sardine calls over the 120-char MaxLineLength threshold.
LibraryMetricsService only queried debrid_cached_torrent_content for the per-provider/type breakdown, so debridav_library_metrics reported zero for usenet-sourced files. Adds a matching query against debrid_cached_usenet_release_content and tags rows with source=torrent|usenet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The log line literally ended 'could not unrestrict link: X because' with nothing after 'because' — the parsed error map was being discarded. Now includes HTTP status + error + error_code (e.g. hoster_unavailable / 19) so operators can tell RD-side outages apart from client bugs without shelling into the pod. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two streams were observed stuck at 0 bitrate for 5+ hours — the consumer (NzbFileResource's out.write() / StreamingService's sendBytesFromHttpStream) was blocked on a socket for a client that had silently disconnected without a clean TCP close. Coroutine cancellation can't preempt blocking Java I/O, so the only reliable unblock is to close the OutputStream itself. Adds a lightweight AtomicBoolean-based watchdog in both paths: writer flips it to true on each chunk; a coroutine ticks once per STALL_TIMEOUT_MS and calls getAndSet(false) — if the result was already false, no bytes moved in a full interval and the output is closed, which throws IOException inside the blocked write and lets cleanup + metric removal proceed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
With OSIV on (Spring's default) the Hibernate session stays open for the entire HTTP request, which for a WebDAV GET that streams for hours meant a Hikari connection stayed pinned the whole time (visible in hikari_connections_active climbing with active streams). Streaming paths already pre-materialize the entities they need (NzbFileResource via toNzbDocument(); DebridFileResource via the captured contents), so sendContent no longer touches lazy state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The test still hit bare /testfile.mp4, which now routes to Spring's static-resource handler (404) because WebDAV moved to /webdav/* in 1.0. Updates the GET and DELETE URIs accordingly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- default.yaml: folder 'Debridav' -> 'debridav' so GrafanaDashboardService's folderTitle filter matches (same case fix that went out to debridav-ci) - platform.json: title 'DebriDav: Platform' -> 'DebriDAV' - health.json (new): full Health dashboard ported from k8s — throughput, latency percentiles, queue depth, DLQ count, oldest message age Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each call site is reached via runBlocking on a Tomcat worker thread, so the worker is parked the whole time anyway — bouncing the JDBC or output-stream write to an IO pool just adds a hop without freeing the caller. DatabaseFileService.getChildren keeps its withContext because the two parallel async branches actually need the dispatcher.
Five call sites used fully-qualified names where a regular import would have worked: @onDelete on NzbContents, the Torrent and NzbDocumentEntity parameter types in the two health-repair handlers, kotlinx.io.IOException in StreamingService, and Delay.milliseconds in ContentStubbingService. The Spring vs MockServer MediaType pair in two ITs stays FQCN-qualified because both are imported.
Spring Data does not auto-wrap interface-level derived delete methods in a transaction (unlike CrudRepository.delete which is annotated on SimpleJpaRepository). Without an outer @transactional caller this fails with "TransactionRequiredException ... cannot reliably process 'remove' call". RealDebridTorrentRepository.deleteByTorrentIdIgnoreCase was the trigger — it's reached from the streaming path via getCachedFiles -> deleteTorrent (when RD reports a torrent has no links left), and that path has no transactional ancestor. TorrentRepository.deleteByHash and ConfigOverrideRepository.deleteAllByPropKeyStartingWith get the same defensive annotation; their callers all happen to be transactional today, but the trap shouldn't sit there waiting for a future caller.
- Drop 'coming in 0.12.0' on NNTP streaming; it's shipped. - Expand Features with the bundled UI, runtime config API, JWT auth, and observability story. - New 'Migrating from 0.11 to 1.0' section covering the WebDAV URL move, NNTP pool-list reshape, health-check config consolidation, and removed keys. - Replace the flat NNTP config table with the new NNTP_POOLS_0_* form and add a dedicated Health check & repair table. - Regroup the main Configuration table into Core / Database / Authentication / Debrid providers / Arrs / UI sections; remove long-dead entries (DEBRIDAV_ROOTPATH, chunk cache knobs, DEBRIDAV_ENABLEFILEIMPORTONSTARTUP) and add the new ones (DEBRIDAV_AUTH_*, DEBRIDAV_WEBDAV-*, DEBRIDAV_UI_GRAFANA_*). - Fix docker tag :v0 → :v1. - Fix REAL-DEBRID_SYNCPOLLRATE default (PT24H, was PT4H). - Fix broken links: example/QUICKSTART.md → example/README.md, docker-compose.yaml → docker-compose.yml. - Rewrite Monitoring section to match today's compose layout. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pulls in the hardcoded forward-threshold-bytes constant (SeekConfig removed) and the drop of the nzb_streams_bytes_total counter (the nzb_streams_bitrate gauge covers the same ground).
Adding a torrent caused a CPU spike that scaled with the number of files. Three pieces overlapped: 1. TorrentService.createTorrent re-parsed the magnet for every file to recover the hash. Hoisted into a single val. 2. DatabaseFileService.createDebridFile was called once per file and each call ran getOrCreateDirectory — global ReentrantLock + ~depth queries + Base58 encoding per segment per call. New createDebridFiles batch entry pre-resolves the unique parent directories once and reuses them for every file. 3. The per-file findByDirectoryAndName triggers a JPQL auto-flush, which would have undermined the new hibernate.jdbc.batch_size=50. The batch entry replaces it with a single findAllByDirectoryInAndNameIn that prefetches all potential collisions, lets us skip the per-iteration query, and lets the ordered inserts at commit actually batch. SabNzbdService.createDebridFilesFromDebridResponse and NzbImportService.executeImport switch to the new batch entry too — same hot path for NZB imports. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…DBC writes' (#28) from perf/torrent-add into 1.0 Reviewed-on: http://192.168.50.245/william/debridav/pulls/28
Jib produces the image end-to-end from Gradle; the hand-maintained Dockerfile hadn't tracked Spring Boot layout changes in ages. The dev/ directory's docker-compose.yml + rclone.conf were an old development convenience superseded by example/docker-compose.yml — same thing, cleaner layering, actually maintained.
Adds a 'Accessing the UI' subsection covering the URL/port, the auth prompt when DEBRIDAV_AUTH_ENABLED is on, and the distinction between the UI at / and WebDAV at /webdav/.
New feature in 1.0: debridav pushes cache invalidations to rclone's RC endpoint on file changes, so long --dir-cache-time values stay safe. Adds a dedicated section with the four config knobs and a note about enabling rclone's RC server.
Was buried as a subsection under 'NNTP / Usenet streaming', which wrongly implied it was NZB-only — the pipeline covers torrents too. Moves the config table up a level and adds prose explaining what gets checked, how repair interacts with Sonarr/Radarr, and the PGMQ-backed queue + UI Health page.
The old docker-compose example was superseded by the current example/ directory ages ago. Removing it from git history keeps repo weight down while leaving the local copy in place for any lingering references.
The version is tracked in gradle.properties (managed by release-please). version.properties was a leftover from the simon-release plugin days and isn't referenced anywhere in the build.
getTorrentInfo logged non-2xx responses but then still called resp.body<TorrentsInfo>() on the error body. kotlinx.serialization threw a SerializationException with no message and no cause, which bubbled all the way up to DebridCachedContentService's catch — that's where the "error getting cached files from REAL_DEBRID : null : null" log came from. Funnel non-2xx through throwDebridProviderException like the other RD endpoints so the actual status + body reach the caller. Also tighten the catch logger so future swallowed exceptions are diagnosable: include the exception class name and full stack trace instead of just .cause and .message. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NNTP streaming and the health-check + repair pipelines are brand-new in 1.0 — they don't have a previous release to migrate from, so documenting 'rename NNTP_HOST → NNTP_POOLS_0_HOST' is meaningless (no one was setting NNTP_HOST in 0.11.x; the feature didn't ship). Pares the migration section back to the genuine 0.11 → 1.0 breaks.
Move @transactional off addMagnet/addTorrent and onto createTorrent so the suspending debrid HTTP call runs outside the transaction. Swap the kotlinx.coroutines Mutex in DatabaseFileService for a ReentrantLock, which removes the runBlocking shim that wrapped purely-blocking JDBC. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.