v0.35.0 Server-Side API for Meta Services
{Service}ServerApi provides typed invocation of meta-methods from server-side code that is not executing inside a meta-call context (e.g., admin panels, framework grains, background jobs).
await grainFactory.GetServerApi<IProfileService>(playerId).AddResourcesAsync(...);
await factory.GetServerApi<IProfileService>(playerId, "1.4.0").MigrateAsync(); // targeting a specific client versionInvocations pass through the server-side cross-entity entry point, ensuring replay recording, subscriber broadcasting, persistence, and sequence advancement occur as usual. Works on cold entities without active subscribers.
Added
{Service}ServerApi+IMetaServerApiFactory(DI handle, registered automatically;IGrainFactoryextensions remain available for callers without DI).- Optional
callerClientVersionparameter to specify which application version the call should execute under (config branch + state migration ceiling). - Applying
[MetaMethod]to a method within[MetaServiceImpl]exposes it on the service surface—the contract can now be inherited from an interface in an external assembly.
Fixed
- Security: Methods with
Mode = Notificationwere not validated on the server—forged packets containing their IDs were being dispatched. Validation rules are now unified across all modes (MetaMethodFacts). - Server-side calls now honor force-patch fan-out (previously restricted to client RPCs).
{Service}ServerApinow retrieves the serializer from the assembly declaring the service rather than the compiling project. Assembly mismatches previously resulted in objects with empty collections silently.[ServiceConfig]accessors now resolve configurations by type rather than by index within the service; on states hosting multiple services, index-based resolution previously targeted the wrong configuration.- Config version resolution now defaults to
CurrentClientVersionacross all code paths—previously, server-side calls to config-bound services failed with"clientAppVersion is required". - Server-side calls now execute under the entity owner's version (resolved from persistent subscribers, working for offline players as well) rather than the current server version. When multiple subscribers exist, the lowest version is selected.
- Configurations are no longer required to be pre-cached—invocations now materialize the configuration for their specified version on demand (fixing previous
"no cached config for X"errors). - Direct RPCs to entities touched by a
CrossOptimisticcall no longer hang indefinitely (the sequence tracking key had been defaulting to an emptystateTypesince v0.33.0). - Hosts lacking an
IConfigVersionResolverno longer log error messages on every entity activation.