Repository navigation
v2.1.0 — outages stop poisoning the cache, and bindings are honoured
Three changes, each from something that actually went wrong on a real library: a large
anime library that came back with hundreds of failures, and a manual binding that was
accepted and then quietly ignored on every run.
Upgrading is a pull. No new environment variable, no config change, and nothing to do
to your database.
A source having a bad day no longer poisons the library
A run against a big anime library came back with 268 failures alternating
jikan: rate limited and jikan: HTTP 504. Four separate faults were behind that, and
the worst one was not the rate limiting:
- A source being unreachable was cached as a verdict. Whatever the reason, the
fallback chain raised "not found", so the title was written to the cache as a failure
and hidden behind an hour of retry backoff. "No source answered" is the absence of an
answer. Those titles are now reported as deferred: nothing is written down, and the
next run picks them straight back up. A verdict from any source still settles a title,
so a genuine miss is cached as the failure it is. - The limiter handed out a whole window at once. A 60-per-minute bucket stocked with
60 tokens delivers the entire minute in its first seconds, which is exactly the spike a
provider's own rolling-window limiter refuses. A window longer than a second now stocks
five seconds' worth, so the traffic is paced instead of bursty. - A refusal was answered with a two-second pause, well inside a rolling minute, so all
three of a title's attempts were spent in the same blocked window. The pause now honours
Retry-After, starts at five seconds otherwise, and doubles while refusals keep coming.
Past a twenty-second hold the title is handed back rather than burning attempts. - Gateway errors were retried almost immediately, because jitter measured from zero can
pick nearly nothing. The backoff now has a floor as well as a ceiling.
Two behaviours follow. A source that keeps failing is stood down for a cool-off, so the
rest of the run goes straight to the next one instead of every title paying its retries.
And once twenty-five titles have been deferred with not one answer from any source, the
run stops early and says so, rather than grinding a library of thousands against an API
that is down.
Deferrals are counted apart from failures everywhere they appear: the console summary,
the run report over the API, the live progress and the run pages. Two related fixes:
failures --library X --retry now clears only the failed entries instead of the whole
library cache, and a run that was stopped early reads "stopped early" rather than
"aborted".
If you already have failures from this, they are still behind their backoff. Clear
just those and run again:
plex-auto-genres failures --library "<your library>" --retry
plex-auto-genres run --library "<your library>"Listing a second source is what makes all of this invisible. For anime, MyAnimeList first
with AniList behind it covers almost everything.
Bindings honour every id scheme they let you name
A binding names an id scheme, not a provider, and a source honours a pin only when it
reads that scheme. Nothing claimed anidb, tvdb or imdb, yet the picker, the API and
the CLI all offered them: the pin was stored, listed among your bindings, and then ignored
by every run, which fell back to the Plex GUID or a title search with no error anywhere.
- What can be translated now is. A pinned id goes through the same AniDB mapping table
a GUID does, so an AniDB pin reaches MyAnimeList as the id it maps to; and TMDB claims
IMDb and TheTVDB ids, cross-referencing them through its own/findendpoint. - What cannot is refused, with the reason, at the point you set it.
That second half was never only about bindings. A film library scanned with the legacy
IMDb agent, or a series library scanned with TheTVDB agent, carries no other id, so every
one of its titles was being searched for by name while Plex knew the exact id all along.
Those libraries now match exactly, and fall back to the search only when the
cross-reference comes back empty.
The item picker now offers only the id schemes, and only the catalogues, that the
library's own sources can use.
TMDB as an anime library's last resort
An anime library can opt in to TMDB as a final fallback, below MyAnimeList and AniList.
TMDB carries most anime as ordinary TV entries, so it answers when the anime sources do
not, with its own taxonomy rather than MyAnimeList's. It is never a default: a library
opts in by listing it, and it needs TMDB_API_KEY.
{ "library": "Animes", "type": "anime", "providers": ["jikan", "anilist", "tmdb"] }In the console it is a toggle under the source presets.
Also: the user agent sent to providers derives from the package version instead of a
pinned string it had already drifted behind. 316 tests, pylint at 10/10.