Skip to content

Fix pre-release review findings for v1.5.6 - #125

Merged
retardgerman merged 1 commit into
devfrom
fix/pre-release-review-1.5.6
Aug 7, 2026
Merged

Fix pre-release review findings for v1.5.6#125
retardgerman merged 1 commit into
devfrom
fix/pre-release-review-1.5.6

Conversation

@retardgerman

Copy link
Copy Markdown
Contributor

Problem

Pre-release review of the v1.5.6 branch (#106) turned up several defects in the Weekly Roundup and library seed/prune code.

Roundup send could fail outright. renderFieldGroup() pushed a field with an empty value whenever a single entry exceeded the 1024-char budget, because value is still "" on the first loop iteration. Discord rejects empty field values with a 400, so the send throws, the scheduler records a failure, and three such ticks open the circuit breaker for the rest of the week.

Episode seed keys pointed at nothing. deriveSeedKeys() built the series and season portion of an episode's key from item.ProviderIds.Tmdb, which for an episode is the episode's TMDB id, not the series'. The resulting series:tmdb:<episode-id> keys never matched the keys built for the real Series and Season items, so the seeder's intended "suppress at any granularity" did nothing for every episode carrying a TMDB id.

The daily prune deleted keys it never re-created. The prune predicate removed id: keys absent from the current scan, but fetchAllLibraryItems() only enumerates Movie/Series/Season/Episode. Any id: key originating from another item type was dropped every 24 hours and re-announced on the next poll.

Smaller issues. The initial prune setTimeout was not cleared on SIGTERM/SIGINT, so a restart within the first five minutes started a full library scan into a process already shutting down. t() logged a warning on every call for a missing key, flooding the log for any incomplete locale. groupItems() shadowed the imported i18n t with a timestamp local. escapeMd() let | through, so a title containing || renders as a Discord spoiler. The changelog carried the 1.5.5 release date, described an idempotency mechanism that was replaced by roundupState.js, and omitted the role-mention feature plus the undici/axios/body-parser/joi security bumps.

Fix

  • renderFieldGroup() truncates entries longer than the budget and only opens a continuation field when the current one has content.
  • deriveSeedKeys() builds episode series/season keys from SeriesId, falling back to SeriesName.
  • The prune predicate no longer touches id: keys; they expire via TTL instead.
  • clearTimeout on the initial prune timer in both signal handlers.
  • t() warns once per locale:key pair, cleared by resetI18nCache().
  • fetchWindowItems() returns { items, rawCount, allowedLibraryCount } instead of hanging expando properties off the returned array and copying them across a .filter().
  • Renamed the t shadow, added | to the escape set, removed the episode debug dump left over from an earlier dedup investigation.
  • Added the missing reseed_library keys to de.json and sv.json.
  • Corrected the changelog date, the roundup idempotency description, and added the missing role-mention and security entries.

fr.json is still missing 48 keys and is deliberately left alone — 4d61bd5 already reverted one machine translation. The per-key warn cap removes the log-flood consequence; the strings need a French speaker.

Verification

renderFieldGroup()'s new logic was exercised against six boundary cases (oversized single entry, oversized followed by normal, normal followed by oversized, 40 normal entries, an entry exactly at 1024 chars, empty list). All produce non-empty, within-budget fields; the first and third cases produced an empty field before this change.

Everything else is static verification only: node --check on each changed module, JSON.parse on each locale, and a module-import smoke test. No live Jellyfin or Discord run.

Not in scope

buildIdentityKey() has the same TMDB-as-series-identity confusion in its Season and Episode branches. Fixing it changes the key format and needs a startup migration plus carries a one-time re-notification risk, so it is deferred to a follow-up issue rather than folded into a review-fix PR.

- renderFieldGroup: truncate oversized entries and never flush an empty
  field value, which Discord rejects with a 400 and which would burn the
  scheduler's weekly failure budget
- librarySeeder: build episode series/season keys from SeriesId, not from
  the episode's own ProviderIds.Tmdb, which never matched a real Series or
  Season key
- libraryPruner: stop pruning "id:" keys — they can originate from item
  types fetchAllLibraryItems does not enumerate, so the daily scan would
  drop them and the next poll would re-notify
- app.js: clear the initial prune timeout on SIGTERM/SIGINT
- i18n: warn once per missing key instead of on every t() call
- weeklyRoundup: return an explicit stats object instead of array expandos,
  rename the `t` shadow in groupItems, escape "|", drop the episode debug dump
- de/sv: add missing reseed_library keys
- CHANGELOG: correct release date, drop the stale
  WEEKLY_ROUNDUP_LAST_POSTED_AT description, add role mention and the
  undici/axios/body-parser/joi security bumps
@retardgerman
retardgerman merged commit ac5115c into dev Aug 7, 2026
2 checks passed
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