Skip to content

refactor(dedup): unify identity key functions into buildIdentityKey#112

Open
retardgerman wants to merge 4 commits into
devfrom
refactor/unified-identity-key
Open

refactor(dedup): unify identity key functions into buildIdentityKey#112
retardgerman wants to merge 4 commits into
devfrom
refactor/unified-identity-key

Conversation

@retardgerman
Copy link
Copy Markdown
Contributor

Problem

stableKeyFor() in roundupFirstSeen.js and buildIdentityKey() in libraryResolver.js both computed stable identifiers for Jellyfin items but used incompatible key formats (m:tmdb:X vs movie:tmdb:X). Any bug fix or logic change had to be made in both places independently, and the two systems could never be cross-referenced.

buildIdentityKey also lacked support for multi-episode ranges (IndexNumberEnd), which stableKeyFor handled.

Fix

  • buildIdentityKey is now the single source of truth for stable item identity
  • stableKeyFor removed; roundupFirstSeen.js imports buildIdentityKey directly
  • buildIdentityKey extended with IndexNumberEnd support for multi-episode entries
  • PersistentMap gains rekey() and keys() to enable key-format migration
  • A one-time startup migration converts existing v1 keys (m:, S:, s:, e: prefixes) to the v2 format so dedup state carries over without items re-appearing as new in the next Weekly Roundup

AI-assisted documentation. Code logic manually verified.

stableKeyFor() in roundupFirstSeen.js and buildIdentityKey() in
libraryResolver.js both computed stable identifiers for Jellyfin items
but used different key formats (m:tmdb:X vs movie:tmdb:X), making them
incompatible and requiring parallel maintenance.

buildIdentityKey() is now the single source of truth. Changes:
- roundupFirstSeen.js imports buildIdentityKey from libraryResolver and
  removes stableKeyFor
- buildIdentityKey gains IndexNumberEnd support for multi-episode ranges
- PersistentMap gains rekey() and keys() to support the migration
- A one-time startup migration converts v1 keys (m:/S:/s:/e: prefixes) to
  the v2 format so existing dedup state carries over without re-appearing
  as new content in the next Weekly Roundup
- Wrap migration IIFE in try/catch so a failure degrades gracefully
  instead of crashing the bot on startup
- Move migrateKey() above the IIFE to remove a fragile hoisting dependency
- Fix episode-range regex to preserve IndexNumberEnd during migration
  (e:SID-S1E1-3 now correctly migrates to series:id:SID:s1e1-3)
- Use non-greedy .+? for SeriesId capture to handle dashed GUID formats
- rekey() no longer overwrites an existing target entry; existing wins
- keys() now evicts expired entries from memory, consistent with get/has
- Log dropped keys at warn and migrated keys at info separately
- flush() now sets dirty=false only after renameSync succeeds, preventing
  a missed flush if the process is killed mid-write
- rekey() logs at debug when a collision causes the old entry to be
  discarded, making migration collisions diagnosable in the field
- Fix logger.warn in libraryResolver to interpolate the error message as
  a string instead of passing the Error object as a second argument
…Discord's 3s window

Fetching full details (images, credits, external_ids) for up to 10 items
in parallel inside the 3-second autocomplete deadline reliably causes
DiscordAPIError[10062] Unknown interaction when TMDB is slow or the cache
is cold. The search and trending endpoints already return title, year, and
media_type — enough to build useful choices without any extra round-trips.

Affects both /search and /trending autocomplete handlers.
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