Expose Service Endpoints#
Endpoint declarations tell users and other plugins how to talk to a running service. They also give the broker a concrete readiness contract: the process is not merely alive, it has become usable.
Declare an Endpoint#
Use EndpointSpec on the service:
import sys
from conda_broker.models import CondaService, EndpointSpec, HealthCheck, ProcessSpec
CondaService(
name="my-provider.api",
summary="Local API used by conda-my-provider",
source="conda-my-provider",
endpoints=(
EndpointSpec(
protocol="http",
host="127.0.0.1",
path="/health",
port_env="PORT",
url_env="SERVICE_URL",
),
),
health_check=HealthCheck(type="http", endpoint="default"),
process=ProcessSpec(
argv=(sys.executable, "-m", "conda_my_provider.server"),
env={"PYTHONUNBUFFERED": "1"},
),
)
When port is omitted, the broker allocates a free local port when the
service starts. It injects that port into the child process before launch.
Read Endpoint Environment Variables#
Every endpoint receives automatic environment variables:
CONDA_BROKER_SERVICE_NAMECONDA_BROKER_ENDPOINT_DEFAULT_PROTOCOLCONDA_BROKER_ENDPOINT_DEFAULT_HOSTCONDA_BROKER_ENDPOINT_DEFAULT_PORTCONDA_BROKER_ENDPOINT_DEFAULT_URL
For non-default endpoint names, the endpoint name is uppercased and non-alphanumeric characters become underscores. Names that collide after normalization are rejected, as are duplicate custom variable names or custom names that overwrite broker variables.
If port_env or url_env is configured, the broker also sets those custom
variables. The example above sets PORT and SERVICE_URL.
IPv6 endpoint URLs use bracketed hosts, for example
http://[::1]:8765/health.
Bind Health Checks to Endpoints#
Endpoint-bound health checks avoid duplicating host and port values:
HealthCheck(type="http", endpoint="default", interval_s=2, timeout_s=1)
HealthCheck(type="tcp", endpoint="control", interval_s=2, timeout_s=1)
Failed health checks remain unknown during start_period_s, which defaults
to five seconds. That gives a process time to bind a dynamically assigned port
before failed probes become restart triggers.
Use start_period_s=0 for services where an immediate failed health check
should restart the process.
Wait for Readiness#
cb start starts processes; it is not a readiness gate. Use cb wait when a
script needs the service to be usable:
cb start my-provider.api
cb wait my-provider.api --timeout 15
To combine explicit startup and readiness waiting:
cb wait my-provider.api --start --timeout 15
cb wait exits with status code zero when the service reports
ready=true. It exits non-zero if the service stops, fails, or never becomes
ready before the timeout.
Inspect Endpoints#
Use cb endpoint to see the resolved endpoint:
cb endpoint my-provider.api
cb endpoint my-provider.api default --json
Stopped services with static ports can still show endpoint URLs. Stopped services with broker-allocated ports show unresolved endpoint fields until the service starts.
For one launch, the broker holds socket reservations while allocating all dynamic endpoints, which prevents two endpoints from receiving the same port. It must release those sockets before the child can bind. Another process can still claim a port in that short interval, so services should exit on bind failure and let restart policy retry with a new allocation.
Query from Another Plugin#
Runtime decisions should use query helpers. They do not start the broker.
from conda_broker import Broker
service = Broker.current().service("my-provider.api")
if endpoint := service.endpoint(ready=True):
use_api(endpoint.url)
else:
use_inline_fallback()
Use service.wait(start=True) only from user-visible commands where
starting the broker and service is an explicit action.