96 lines
5.6 KiB
Markdown
96 lines
5.6 KiB
Markdown
# @suaveplan/service-discovery - Universal service discovery primitives: ServiceRegistry with TTL/expiry, query, AbortSignal-aware watch, optional storage persistence and EventBusLike integration. Shared foundation for every network-discovery-* plugin.
|
|
|
|
## Summary
|
|
|
|
Universal service-registry primitives. Provides the shared
|
|
`ServiceDescriptor`, `ServiceQuery`, `RegistryEvent`, and `ServiceRegistry`
|
|
contract consumed by every Wave-2 `network-discovery-*` plugin.
|
|
|
|
<!-- begin:auto-docs -->
|
|
## Documentation tree
|
|
|
|
- [service-registry](./src/core/service-registry/service-registry.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [service-registry](./src/core/service-registry/service-registry.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
<!-- end:auto-docs --> - [service-registry](./src/core/service-registry/service-registry.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [service-registry](./src/core/service-registry/service-registry.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [service-registry](./src/core/service-registry/service-registry.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [service-registry](./src/core/service-registry/service-registry.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_ - [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_ - [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ - [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_
|
|
## Install
|
|
|
|
```bash
|
|
bun add @suaveplan/service-discovery
|
|
```
|
|
|
|
## Basic usage
|
|
|
|
```ts
|
|
import { ServiceRegistry } from "@suaveplan/service-discovery";
|
|
|
|
const registry = new ServiceRegistry({ ttlMs: 30_000 });
|
|
|
|
registry.register({
|
|
id: "api-1",
|
|
name: "api",
|
|
address: "10.0.0.1:8080",
|
|
status: "healthy",
|
|
region: "us-east-1",
|
|
tags: ["v1"],
|
|
});
|
|
|
|
const healthy = registry.query({ name: "api", status: "healthy" });
|
|
```
|
|
|
|
## Advanced usage: watch + bus + persistence
|
|
|
|
```ts
|
|
import { ServiceRegistry } from "@suaveplan/service-discovery";
|
|
import type { EventBusLike } from "@suaveplan/types";
|
|
|
|
declare const bus: EventBusLike<{
|
|
"service:registered": import("@suaveplan/service-discovery").ServiceDescriptor;
|
|
"service:deregistered": import("@suaveplan/service-discovery").ServiceDescriptor;
|
|
"service:expired": import("@suaveplan/service-discovery").ServiceDescriptor;
|
|
}>;
|
|
|
|
declare const storage: import("@suaveplan/service-discovery").ServiceRegistryStorageLike;
|
|
|
|
const registry = new ServiceRegistry({
|
|
ttlMs: 30_000,
|
|
maxServices: 5_000,
|
|
bus,
|
|
storage,
|
|
persistKey: "service-registry:v1",
|
|
});
|
|
|
|
await registry.load();
|
|
|
|
const ac = new AbortController();
|
|
(async () => {
|
|
for await (const ev of registry.watch({ name: "api" }, ac.signal)) {
|
|
console.log(ev.type, ev.service.id);
|
|
}
|
|
})();
|
|
|
|
// later:
|
|
await registry.flush();
|
|
ac.abort();
|
|
registry.dispose();
|
|
```
|
|
|
|
## What ships
|
|
|
|
- `ServiceRegistry` — in-memory store with TTL expiry, query, AbortSignal-
|
|
aware `watch()` async iterator, optional persistent backing, optional
|
|
`EventBusLike` fan-out.
|
|
- Typed error class `SvcDiscError` + frozen `SVC_DISC_CODES` registry
|
|
(`DUPLICATE_REGISTRATION` / `QUERY_INVALID` / `REGISTRY_FULL` /
|
|
`INVALID_OPTIONS`).
|
|
- Zod schemas at every public boundary.
|
|
- OTel: `svc_disc.registrations_total{outcome}`, `svc_disc.queries_total`,
|
|
`svc_disc.query_duration_ms`, `svc_disc.active_services` gauge.
|
|
|
|
See each feature module's sibling `.md` for the full surface.
|