core.service_base module
Service boot contract shared by every Stargazer microservice.
Defines StargazerService, the abstract base that runs a fixed
boot sequence (Redis connect/ping, the subclass’s on_start,
service-registry registration, and an HTTP health server via
HealthServer) and a matching graceful
shutdown. Every entry point (gateway / inference / agents /
consolidation / web) subclasses it and implements on_start and
run.
- class core.service_base.StargazerService(service_name, instance_id, redis_client=None, redis_required=True, use_health_server=True)[source]
Bases:
ABCAbstract base class establishing the 9-phase boot contract.
Every Stargazer microservice (gateway / inference / agents / consolidation / web) subclasses this to inherit a uniform startup and shutdown lifecycle, so boot ordering – Redis ping gate, subclass init, service-registry registration, health server – is identical across the fleet and bugs in one tier cannot diverge from another. Subclasses fill in the three abstract hooks (
on_start(),run(),on_stop()) whileboot()andshutdown()orchestrate the fixed sequence around them.Touches Redis (ping, registration via
register_service(), deregistration viaderegister_service()) and an HTTP health endpoint throughHealthServer. It is never instantiated directly – each*_main.pyentry point defines a concrete subclass (InferenceService,AgentsService,WebService,GatewayService,ConsolidationService) that callssuper().__init__and is launched from that module’smainunderasyncio.run.- __init__(service_name, instance_id, redis_client=None, redis_required=True, use_health_server=True)[source]
Capture service identity and wire up the optional health server.
Performs only the cheap, synchronous Phase 1 (local init) portion of the boot contract; the network-touching phases run later in
boot(). The supplied Redis client is stored for use byboot()/shutdown()(ping, service-registry registration, deregistration) and by subclasses. Whenuse_health_serveris true and a Redis client is present, aHealthServeris constructed (but not started here) bound to the port from theSG_HEALTH_PORTenvironment variable, defaulting to9090; it is started later inboot()’s Phase 9. No callers constructStargazerServicedirectly – it is abstract and each microservice entry point (gateway / inference / agents / consolidation / web) subclasses it and reaches this viasuper().__init__.- Parameters:
service_name (
str) – Logical service name used in boot logs and in the service registry (e.g."inference").instance_id (
str) – Unique identifier distinguishing this process from other replicas of the same service.redis_client – An async Redis client, or
Noneto run without Redis (in which case the registry, ping gate, and health server are all skipped).redis_required (
bool) – When true and the Redis ping inboot()fails, the process hard-fails viasys.exit(1); when false the failure is logged and boot continues.use_health_server (
bool) – When true (and Redis is present), build aHealthServerto expose HTTP health.
- async boot()[source]
Run the full 9-phase startup sequence and bring the service live.
Drives the service from local init to a registered, health-serving process: it sleeps a random jitter (0-2s) to desynchronize replica starts, pings Redis and hard-fails the process if the ping fails and
redis_requiredis set, runs the subclass’son_start(), registers the instance in the service registry, and starts the health server. The jitter and ping gate exist so a thundering herd of restarts does not stampede Redis and so a service never claims work while its backing store is unreachable.Touches Redis (
pingplus asetofsg:registry:service:...with status"starting"viaregister_service()), may bind the HTTP health port, and on a required-Redis ping failure callssys.exit(1). Called by each microservice’smain(ininference_main.py,agents_main.py,consolidation_main.py,web_main.py,gateway_main.py) immediately beforeservice.run(), and exercised bytests/core/migration.- Raises:
SystemExit – Via
sys.exit(1)whenredis_requiredis true and the Redis ping fails.
- async shutdown()[source]
Tear the service down gracefully in reverse boot order.
Counterpart to
boot(): it stops the HTTP health server (so the instance immediately reports unready), removes the instance from the service registry, and then runs the subclass’son_stop()cleanup. Ordering matters – deregistering and dropping health beforeon_stop()ensures operators and load balancers stop routing to a process that is mid-teardown.Touches Redis by deleting the
sg:registry:service:...key viaderegister_service()and closes the health port. Invoked from the SIGINT/SIGTERM signal handlers installed in each microservice’smain(e.g.asyncio.create_task(service.shutdown())ininference_main.py/gateway_main.py/web_main.py/consolidation_main.py/agents_main.py) and asserted bytests/core/migration/test_service_base.py.
- abstractmethod async on_start()[source]
Subclass hook for tier-specific startup, run during boot.
Abstract extension point invoked by
boot()(its phase 3-7) after the Redis ping succeeds but before registry registration and the health server start, so each tier can stand up its own machinery – loading tools, building platform adapters, wiring stream consumers, initializing observability – on a verified Redis connection. Has no behavior here; it must be overridden.Called by
boot(); the concrete implementations live in the*_main.pyservice classes (InferenceService.on_start,GatewayService.on_start, etc.) and are exercised directly by thetests/core/migrationsuite.
- abstractmethod async run()[source]
Subclass hook for the main service loop, run after boot.
Abstract extension point that holds the service’s long-lived work – typically consuming a Redis stream or serving HTTP – and is expected to block until shutdown is signalled. Each tier’s
mainawaits this immediately afterboot()returns, so it defines what the process actually does for its lifetime. Has no behavior here; it must be overridden.Called by each microservice’s
mainviaawait service.run()(ininference_main.py,gateway_main.py,web_main.py,consolidation_main.py,agents_main.py), right afterservice.boot().
- abstractmethod async on_stop()[source]
Subclass hook for tier-specific cleanup, run during shutdown.
Abstract extension point invoked by
shutdown()after the health server is stopped and the instance is deregistered, giving each tier a place to release whaton_start()andrun()stood up (platform adapters, schedulers, consumers, sockets). Has no behavior here; it must be overridden.Called by
shutdown(); concrete implementations live in the*_main.pyservice classes (e.g.WebService.on_stopdrives a graceful uvicorn exit,GatewayService.on_stopstops platform adapters) and are covered bytests/core/migration.