Skip to content

feat: bump Geo/Invision/Servers clients and enable L1 read-only caching - #55

Merged
frasermolyneux merged 1 commit into
mainfrom
agents/update-portal-server-events-caching
Aug 3, 2026
Merged

feat: bump Geo/Invision/Servers clients and enable L1 read-only caching#55
frasermolyneux merged 1 commit into
mainfrom
agents/update-portal-server-events-caching

Conversation

@frasermolyneux

Copy link
Copy Markdown
Owner

Summary

Bump the three MX / XtremeIdiots client packages to the versions we just released and turn on the safe, read-only L1 in-memory caching those packages now ship, with startup-composition tests that guard against a repeat of the 4.2.21-era boot crash. Requested via the coding-agent task "Update portal-server-events to the latest XtremeIdiots/MX client packages…".

Closes #

Type of change

  • bugfix
  • feature
  • chore / refactor
  • docs
  • infra (Terraform)
  • ci (GitHub Actions / Dependabot)
  • dependencies
  • breaking change

Required reading consulted

  • AGENTS.md (repo brief)
  • .github/copilot-instructions.md (repo orientation)
  • .github-copilot/.github/instructions/personal.working-preferences.instructions.md (always-on rules)
  • Stack-specific instruction files referenced in AGENTS.md (standards.*, patterns.*, platform.*, shared.*)

Validation evidence

Build

$ dotnet build src\XtremeIdiots.Portal.Server.Events.slnx --nologo -v minimal
  XtremeIdiots.Portal.Server.Events.Abstractions.V1 -> ...\XtremeIdiots.Portal.Server.Events.Abstractions.V1.dll
  XtremeIdiots.Portal.Server.Events.Processor.App   -> ...\XtremeIdiots.Portal.Server.Events.Processor.App.dll
  XtremeIdiots.Portal.Server.Events.Processor.App.Tests -> ...\XtremeIdiots.Portal.Server.Events.Processor.App.Tests.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:04.35

Tests

$ dotnet test src\XtremeIdiots.Portal.Server.Events.slnx --nologo --no-build -v minimal
Test run for ...\XtremeIdiots.Portal.Server.Events.Processor.App.Tests.dll (.NETCoreApp,Version=v9.0)
A total of 1 test files matched the specified pattern.

Passed!  - Failed:     0, Passed:   387, Skipped:     0, Total:   387, Duration: 372 ms

Ten of those 387 are the new / expanded startup-composition tests under Tests/Startup/:

  • RepositoryApiClientRegistrationTests (3, unchanged)
  • GeoLocationApiClientRegistrationTests (3 — builds real provider with caching enabled; resolves IGeoLocationApiClient, v1 and v1.1 IGeoLookupApi, and IMxCache)
  • InvisionApiClientRegistrationTests (2 — resolves IInvisionApiClient and each Core / Downloads / Forums typed sub-API with caching enabled)
  • ServersApiClientRegistrationTests (2 — resolves IServersApiClient + Cod2Rcon.V1 / Cod4Rcon.V1 / Cod5Rcon.V1 / CoD4xRcon.V1 / Maps.V1)

Format check

$ dotnet format src\XtremeIdiots.Portal.Server.Events.slnx --verify-no-changes
(no output = pass)

Other

  • code-review sub-agent: No significant issues found in the reviewed changes. See "Reviewer focus areas" for the summary of what was verified.

Risk and rollout

  • Blast radius: portal-server-events Processor Function App only (dev + prd). No infra, no RBAC, no queue-contract changes. Caching is L1 in-memory per Function App instance — nothing distributed touches other services.
  • Auto-deploys on merge? Yes — dev auto-deploys on merge to main via deploy-dev.yml; prd promotes via deploy-prd.yml.
  • Manual steps post-merge: None.
  • Rollback plan: Revert this PR. All three package bumps are backward compatible in-app; the previous behaviour is "same client, no caching" which is what runs today.

Confidence rationale (mirrors the code-review findings):

  • The 4.2.21-era ArgumentException: The expression must invoke a method declared by ...IAdminActionsApi ... root cause is fixed upstream in MX.Api.Client 2.3.77 (already at head), which uses the reflection-free SharedCacheConfiguration to scope each captured cache policy to its matching typed sub-API instead of walking one expression across siblings. All three registration helpers now use .WithCachePartition(CachePartition).WithCaching(c => c.UseLibraryDefaults()) — the exact chain re-enabled for Repository in feat: roll Repository client to 4.2.22 and re-enable consumer L1 caching #54.
  • The new GeoLocationApiClientRegistrationTests / InvisionApiClientRegistrationTests / ServersApiClientRegistrationTests build the real ServiceProvider (with validateScopes: true) and resolve every typed sub-API the Processor App touches at runtime. A future package bump that regresses the shared-caching composition would fail these tests before it reached the Functions host.
  • No read-then-mutate-then-re-read patterns exist for the cached surfaces in this codebase: Invision usage is confined to Forums.PostTopic (uncached by the library); GeoLocation call sites (PlayerConnectedProcessor, PlayerIpResolvedProcessor, ServerStatusProcessor, VpnProtectionEvaluation, WhoAmICommand) are pure GetIpIntelligence reads. No .NotCached<...>(...) exclusions were required.

Consumer impact

No published contracts changed. The Abstractions NuGet package (XtremeIdiots.Portal.Server.Events.Abstractions.V1) and every queue-name constant it exports are untouched — the diff is entirely inside the Processor App, its csproj, and its test project. portal-server-agent is not affected.

Reviewer focus areas

  • The three new registration helpers (GeoLocationApiClientRegistration, InvisionApiClientRegistration, ServersApiClientRegistration) intentionally mirror RepositoryApiClientRegistration. CachePartition is a single constant reused via const string = RepositoryApiClientRegistration.CachePartition so all four helpers share one partition namespace — verified safe because each AddTypedApiClient call scopes cache keys per client type.
  • The recommended "second call served from cache within TTL" behaviour test was intentionally skipped: the MX.GeoLocation.Api.Client.Testing package's FakeVersionedGeoLookupApi replaces the typed sub-API in the container, which bypasses the DI cache decorator, so it cannot demonstrate a real cache hit. The DI composition test (which additionally resolves IMxCache) covers the primary production-startup risk the task called out. Behavioural correctness of the cache is guaranteed by MX.Api.Client / MX.GeoLocation.Api.Client's own tests.

Agent attestation

  • Ran code-review sub-agent; High/Medium findings resolved or justified above in Reviewer focus areas
  • PR body cites each acceptance criterion from the linked issue
  • No client secrets, GUIDs, connection strings, or hard-coded subscription IDs introduced (standards.oidc-and-secrets.instructions.md)

Bump three client packages to their latest crash-safe releases and turn on
the library-default in-memory read-only caching now that MX.Api.Client 2.3.77
scopes each captured policy via SharedCacheConfiguration:

- MX.GeoLocation.Api.Client.V1 1.2.96 -> 1.2.98 (caching on)
- MX.InvisionCommunity.Api.Client 1.0.61 -> 1.0.63 (caching on)
- XtremeIdiots.Portal.Integrations.Servers.Api.Client.V1 4.1.9 -> 4.1.14
  (currency + crash-safety; no defaults to enable)
- XtremeIdiots.Portal.Integrations.Servers.Abstractions.V1 4.1.9 -> 4.1.14
  (transitive dependency lockstep)

Registration is extracted into GeoLocationApiClientRegistration,
InvisionApiClientRegistration, and ServersApiClientRegistration helpers
so Program.cs and the boot-composition tests share a single source of
truth for each client's option chain — matching the RepositoryApiClient
pattern re-enabled in #54.

Add xUnit startup-composition tests that build the real ServiceProvider
with caching enabled and resolve every typed sub-API the Processor App
touches at runtime (Geo v1 + v1.1 GeoLookup, Invision Core/Downloads/
Forums, Servers Cod2/Cod4/Cod5/CoD4x Rcon + Maps). A dedicated Geo test
also resolves IMxCache to guard the L1 auto-wiring. Any future regression
of the 2.3.76-era 'The expression must invoke a method declared by ...'
ArgumentException now fails these tests instead of the Functions host.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 3, 2026 19:33
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Dependency Review

The following issues were found:
  • ✅ 0 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 4 package(s) with unknown licenses.
See the Details below.

License Issues

src/XtremeIdiots.Portal.Server.Events.Processor.App/XtremeIdiots.Portal.Server.Events.Processor.App.csproj

PackageVersionLicenseIssue Type
MX.GeoLocation.Api.Client.V11.2.98NullUnknown License
MX.InvisionCommunity.Api.Client1.0.63NullUnknown License
XtremeIdiots.Portal.Integrations.Servers.Abstractions.V14.1.14NullUnknown License
XtremeIdiots.Portal.Integrations.Servers.Api.Client.V14.1.14NullUnknown License

OpenSSF Scorecard

PackageVersionScoreDetails
nuget/MX.GeoLocation.Api.Client.V1 1.2.98 UnknownUnknown
nuget/MX.InvisionCommunity.Api.Client 1.0.63 UnknownUnknown
nuget/XtremeIdiots.Portal.Integrations.Servers.Abstractions.V1 4.1.14 UnknownUnknown
nuget/XtremeIdiots.Portal.Integrations.Servers.Api.Client.V1 4.1.14 UnknownUnknown

Scanned Files

  • src/XtremeIdiots.Portal.Server.Events.Processor.App/XtremeIdiots.Portal.Server.Events.Processor.App.csproj

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Processor Function App to newer GeoLocation / Invision Community / Servers client package versions and centralizes their DI registration into single-purpose helpers, enabling the new safe, read-only L1 in-memory caching where supported and adding startup-composition tests to guard against regressions like the historical boot crash.

Changes:

  • Bump GeoLocation, Invision Community, and Servers integration client package versions in the Processor App.
  • Introduce DI registration helpers for GeoLocation, Invision, and Servers clients (mirroring the existing Repository registration helper) and enable library-default L1 caching for GeoLocation + Invision with a shared cache partition.
  • Add startup-composition tests that build a validating ServiceProvider and resolve key typed sub-APIs (and IMxCache for GeoLocation) to catch DI/caching composition regressions at test time.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/XtremeIdiots.Portal.Server.Events.Processor.App/XtremeIdiots.Portal.Server.Events.Processor.App.csproj Bumps GeoLocation/Invision/Servers client package versions.
src/XtremeIdiots.Portal.Server.Events.Processor.App/Program.cs Switches to the new registration helpers; enables conditional GeoLocation registration without breaking boot when unconfigured.
src/XtremeIdiots.Portal.Server.Events.Processor.App/GeoLocationApiClientRegistration.cs Adds centralized GeoLocation client registration with cache partition + library-default L1 caching and a “try-add if configured” overload.
src/XtremeIdiots.Portal.Server.Events.Processor.App/InvisionApiClientRegistration.cs Adds centralized Invision client registration with cache partition + library-default L1 caching.
src/XtremeIdiots.Portal.Server.Events.Processor.App/ServersApiClientRegistration.cs Adds centralized Servers client registration (no caching enabled, per package behavior).
src/XtremeIdiots.Portal.Server.Events.Processor.App.Tests/Startup/GeoLocationApiClientRegistrationTests.cs Adds DI composition tests that resolve GeoLocation APIs and IMxCache with caching enabled.
src/XtremeIdiots.Portal.Server.Events.Processor.App.Tests/Startup/InvisionApiClientRegistrationTests.cs Adds DI composition tests that resolve Invision client and typed sub-APIs with caching enabled.
src/XtremeIdiots.Portal.Server.Events.Processor.App.Tests/Startup/ServersApiClientRegistrationTests.cs Adds DI composition tests that resolve Servers client and representative typed sub-APIs after the bump.

@sonarqubecloud

sonarqubecloud Bot commented Aug 3, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

🏗️ Terraform Plan

🌍 Environment: dev

✅ Validate — Passed

✅ Plan

No changes. Your infrastructure matches the configuration.

@frasermolyneux
frasermolyneux merged commit 08de830 into main Aug 3, 2026
19 checks passed
@frasermolyneux
frasermolyneux deleted the agents/update-portal-server-events-caching branch August 3, 2026 19:42
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.

2 participants