pub trait DirectoryClient: Send + Sync {
// Required methods
fn resolve_grpc_service<'life0, 'life1, 'async_trait>(
&'life0 self,
service_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ServiceEndpoint, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait;
fn resolve_rest_service<'life0, 'life1, 'async_trait>(
&'life0 self,
gear_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ServiceEndpoint, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait;
fn get_openapi_spec<'life0, 'life1, 'async_trait>(
&'life0 self,
gear_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait;
fn list_instances<'life0, 'life1, 'async_trait>(
&'life0 self,
gear: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<ServiceInstanceInfo>, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait;
fn list_all_instances<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<ServiceInstanceInfo>, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait,
Self: 'async_trait;
fn register_instance<'life0, 'async_trait>(
&'life0 self,
info: RegisterInstanceInfo,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait,
Self: 'async_trait;
fn deregister_instance<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
gear: &'life1 str,
instance_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait;
fn send_heartbeat<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
gear: &'life1 str,
instance_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait;
// Provided method
fn resolve_by_labels<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
gear: &'life1 str,
selector: &'life2 LabelSelector,
) -> Pin<Box<dyn Future<Output = Result<Vec<ServiceInstanceInfo>, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait { ... }
}Expand description
Directory API trait for service discovery and instance management
This trait defines the contract for interacting with the gear directory. It can be implemented by:
- A local implementation that delegates to
GearManager - A gRPC client for out-of-process gears
Required Methods§
Sourcefn resolve_grpc_service<'life0, 'life1, 'async_trait>(
&'life0 self,
service_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ServiceEndpoint, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn resolve_grpc_service<'life0, 'life1, 'async_trait>(
&'life0 self,
service_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ServiceEndpoint, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
Resolve a gRPC service by its logical name to an endpoint
Sourcefn resolve_rest_service<'life0, 'life1, 'async_trait>(
&'life0 self,
gear_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ServiceEndpoint, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn resolve_rest_service<'life0, 'life1, 'async_trait>(
&'life0 self,
gear_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ServiceEndpoint, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
Resolve a REST endpoint (HTTP base URL) for a gear by its name.
Returns the base URL (e.g. http://billing:8080) that callers use to
make REST requests to the resolved gear.
Sourcefn get_openapi_spec<'life0, 'life1, 'async_trait>(
&'life0 self,
gear_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn get_openapi_spec<'life0, 'life1, 'async_trait>(
&'life0 self,
gear_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
Retrieve the OpenAPI spec (JSON) published by a gear.
Sourcefn list_instances<'life0, 'life1, 'async_trait>(
&'life0 self,
gear: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<ServiceInstanceInfo>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn list_instances<'life0, 'life1, 'async_trait>(
&'life0 self,
gear: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<ServiceInstanceInfo>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
List all service instances for a given gear.
Entries are spec-free: only the openapi_spec_hash is carried, never
the full OpenAPI document, so a multi-instance response stays
bounded regardless of spec size. Callers fetch the document out-of-band
via get_openapi_spec; the hash lets a consumer
detect a spec change without inlining N copies of the document.
An endpoint-less instance is still returned (endpoint/rest_endpoint =
None, never an empty-URI sentinel): no-endpoint, not an error. Only
list_all_instances, which needs a dialable
URI, drops such entries.
Sourcefn list_all_instances<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<ServiceInstanceInfo>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
fn list_all_instances<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<ServiceInstanceInfo>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
List every service instance across all registered gears.
Used by the edge gateway to discover which gears (and their REST
endpoints) to reverse-proxy. This is a lightweight discovery snapshot.
Like every enumeration path, it is spec-free: entries carry only the
openapi_spec_hash, never the full OpenAPI document, even when the
backing store holds a stored specification. The edge fetches a gear’s
document once, on first discovery, via
get_openapi_spec.
The returned instances also do not carry labels: every
implementation applies ServiceInstanceInfo::without_labels so the
snapshot omits them identically regardless of transport. Labels drive
the targeted resolve_by_labels path, not
this snapshot.
Sourcefn register_instance<'life0, 'async_trait>(
&'life0 self,
info: RegisterInstanceInfo,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
fn register_instance<'life0, 'async_trait>(
&'life0 self,
info: RegisterInstanceInfo,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
Register a new gear instance with the directory
Sourcefn deregister_instance<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
gear: &'life1 str,
instance_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn deregister_instance<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
gear: &'life1 str,
instance_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Deregister a gear instance (for graceful shutdown)
Sourcefn send_heartbeat<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
gear: &'life1 str,
instance_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn send_heartbeat<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
gear: &'life1 str,
instance_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Send a heartbeat for a gear instance to indicate it’s still alive
Provided Methods§
Sourcefn resolve_by_labels<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
gear: &'life1 str,
selector: &'life2 LabelSelector,
) -> Pin<Box<dyn Future<Output = Result<Vec<ServiceInstanceInfo>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn resolve_by_labels<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
gear: &'life1 str,
selector: &'life2 LabelSelector,
) -> Pin<Box<dyn Future<Output = Result<Vec<ServiceInstanceInfo>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Resolve instances of gear whose labels satisfy selector.
Matching is equality-AND (k8s matchLabels): an instance matches iff
it carries every (key, value) pair in the selector; an empty
selector matches every instance of the name.
The returned set is not health-filtered — matched instances are
returned regardless of readiness/heartbeat state, each carrying its
instance_id, labels, endpoints, and live
state. Applying liveness policy (e.g.
keeping only InstanceState::is_serving) is the caller’s
responsibility.
Nor is it endpoint-filtered: a matched instance that advertises no
endpoint yet is still returned (endpoint/rest_endpoint = None) —
no-endpoint, not an error — so the caller can fall back rather than
have the match silently hidden.
Returned entries are spec-free on every implementation — the full
OpenAPI document is omitted (only its hash is carried), so the
polled resolve payload stays bounded; the caller fetches documents via
get_openapi_spec. This holds regardless of
whether the selector is empty. The default body enumerates via
list_instances and filters in-process;
transport-backed clients (e.g. the gRPC client) override it to push the
selector server-side.
Label-based selection is effectively out-of-process only. Labels are
published from the OoP serve path’s configuration (oop_http.labels);
the in-process registration path (grpc-hub start phase /
run_directory_register_phase) has no label source, so an in-process
gear carries no labels and a non-empty selector never matches it. This
matches the deployment model: shards/peers are distinct instances
(separate pods/processes), which is inherently the OoP topology.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".