Services
Services supply the shared, run-scoped capabilities and data that components, the policy, and the engine itself draw on. Where a component computes a value, a service provides a resource: the decoded records and dataset statistics, the process state such as device, seed, and rank, the backing record store, the batched data loaders, and the metric computations. Components request the services they need by name.
Each service is configured under its own key in the services section. The
built-in services are independent subsystems, each documented on its own page:
services:
state: { ... }
data: { ... }
record: { ... }
decode: { ... }
metrics: { ... }
How it Works
A service is a plugin keyed by its section name. A service may declare dependencies on other services; the engine builds the configured services, verifies that every declared dependency is present, and attaches them in dependency order so that each service can rely on those it depends upon. A dependency cycle is reported as a configuration error.
Registering a new service
The services section accepts user-defined services in addition to the built-in
set. A service is a subclass of Service that declares a name and
version and is registered with ServiceFactory; it may list other services
it needs in the deps class attribute so the engine attaches them first.
from typing import Any, ClassVar
from icegraph.engine.services.service import Service
from icegraph.engine.services.factory import ServiceFactory
from .config import MyServiceConfig
class MyService(Service[MyServiceConfig]):
name: ClassVar[str] = "my-service"
version: ClassVar[int] = 1
deps = ("state",)
@classmethod
def validate_config(cls, config: dict[str, Any]) -> MyServiceConfig:
return MyServiceConfig(**config)
def build(self) -> None:
...
ServiceFactory.register(MyService)
Once registered, other services or components reach it through
services.require("my-service").