Skip to content

fix(schema): tmdb.api_key is restart-required, not live — v0.46.0 - #35

Merged
detain merged 1 commit into
masterfrom
fix/tmdb-api-key-restart-true
Jul 28, 2026
Merged

fix(schema): tmdb.api_key is restart-required, not live — v0.46.0#35
detain merged 1 commit into
masterfrom
fix/tmdb-api-key-restart-true

Conversation

@detain

@detain detain commented Jul 28, 2026

Copy link
Copy Markdown
Owner

What

Corrects tmdb.api_key in schemas/server-settings.schema.json from
"restart": false to "restart": true, discloses the requirement in the key's
helpText, and ships it as v0.46.0.

Why restart: false was factually wrong

TmdbProvider is registered as a PHP-DI factory(). PHP-DI caches every
resolved entry — factories included — in Container::$resolvedEntries
(vendor/php-di/php-di/src/Container.php), so the provider is a per-container
singleton that captures the API key by value at construction.

  • One container is built per worker in onWorkerStart (start.php).
  • phlix-library-scan resolves it eagerly at fork time
    (LibraryScanWorkerLibraryMetadataMatcherTmdbProvider).
  • There is no TTL, no invalidation hook, and no cross-worker propagation.

A newly saved key is therefore inert until the workers are recycled — while the
admin SPA rendered it as taking effect immediately.

This is the same "Class (b) RESTART" shape already documented for the
server.rate_limit.* keys in tests/Schema/ServerSettingsSchemaTest.php
("the limiters are factory() closures that capture max/window BY VALUE at
container-build time … frozen into DI and can never apply live"). The fact that
SettingsRepository::getEffective() itself does an uncached SELECT on every
call is irrelevant once the value has been captured.

Scope

No key added or removed, so the suite's hard-locked property count is unchanged.

Verification

Gate Result
./vendor/bin/phpunit OK — 1025 tests, 83028 assertions
composer stan [OK] No errors
composer cs clean — 59 files, 0 violations

Follow-up (not in this PR)

An audit of the remaining 38 restart: false keys in this schema found 7 more
in the same Class (b) shape, several of which contradict their own consuming
code's docblocks:

  • matching.noise_suffixesfactory() injected as a constructorParameter
    into MediaScanner; its own comment says "computed once at construction".
  • metadata.provider_priority, metadata.genres_mode — captured into the
    PriorityConfig factory; comment says "resolved ONCE when first built
    (per worker cycle, not per request)".
  • lastfm.api_key, lastfm.shared_secret, lastfm.enabled — overlaid at
    route-build time; Application::applyLastfmOverrides()'s docblock literally
    asserts "the lastfm.* schema keys carry \"restart\": true\"", which this
    schema contradicts.
  • port-forward.port_forwarding.upnp_enabled — read via EffectiveConfig::file()
    at container-build time; NetworkServicesProvider's comment says the values are
    "genuinely admin-controlled (on reload)".

Raised separately so this PR stays a single-key correction.

🤖 Generated with Claude Code

`schemas/server-settings.schema.json` declared `"restart": false` for
`tmdb.api_key`, so the admin SPA promised a saved key applied immediately.
That promise was false.

TmdbProvider is registered as a PHP-DI `factory()`, and PHP-DI caches every
resolved entry -- factories included -- in `Container::$resolvedEntries`, so
the provider is a per-container singleton that captures the key BY VALUE at
construction. One container is built per worker in `onWorkerStart`, and the
`phlix-library-scan` worker resolves it eagerly at fork time
(LibraryScanWorker -> LibraryMetadataMatcher -> TmdbProvider). With no TTL, no
invalidation hook and no cross-worker propagation, a newly saved key stays
inert until the workers are recycled.

This is the same "Class (b) RESTART" shape already documented for the
`server.rate_limit.*` keys in tests/Schema/ServerSettingsSchemaTest.php: a
value frozen into DI at container-build time can never apply live, regardless
of `SettingsRepository::getEffective()` doing an uncached SELECT per call.

Also discloses the requirement in the key's admin-facing helpText, matching
how the `process.<worker>.enabled` keys disclose their restart semantics.

No key added or removed -- the hard-locked property count is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@codacy-production

codacy-production Bot commented Jul 28, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity · 0 duplication

Metric Results
Complexity 0
Duplication 0

View in Codacy

🟢 Coverage ∅ diff coverage · +0.00% coverage variation

Metric Results
Coverage variation +0.00% coverage variation (-1.00%)
Diff coverage diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (d82185a) 1016 829 81.59%
Head commit (9af498a) 1016 (+0) 829 (+0) 81.59% (+0.00%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#35) 0 0 ∅ (not applicable)

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.29%. Comparing base (d82185a) to head (9af498a).

Additional details and impacted files
@@            Coverage Diff            @@
##             master      #35   +/-   ##
=========================================
  Coverage     81.29%   81.29%           
  Complexity      414      414           
=========================================
  Files            50       50           
  Lines          1160     1160           
=========================================
  Hits            943      943           
  Misses          217      217           
Flag Coverage Δ
phpunit 81.29% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@detain
detain merged commit 0248d7d into master Jul 28, 2026
11 checks passed
@detain
detain deleted the fix/tmdb-api-key-restart-true branch July 28, 2026 15:52
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