Aggregate seed provider
Это содержимое пока не доступно на вашем языке.
AggregateSeedProvider wraps multiple seed providers and tries
them in order, returning the first non-empty result. Useful
when:
- You want DNS first, fall back to static seeds if DNS is unreachable.
- The same code runs in multiple environments: K8s for prod, static config for local dev.
- You’re doing disaster recovery — primary discovery mechanism + backup.
import { Cluster, ClusterOptions, AggregateSeedProvider, KubernetesApiSeedProvider, KubernetesApiSeedProviderOptions, DnsSeedProvider, DnsSeedProviderOptions, ConfigSeedProvider, ConfigSeedProviderOptions,} from 'actor-ts';
const kubernetesApiSeedProviderOptions = KubernetesApiSeedProviderOptions.create() .withNamespace(namespace) .withServiceName(labelSelector) .withSystemName('my-app') .withPort(2552);const dnsSeedProviderOptions = DnsSeedProviderOptions.create() .withHostname('_actor-ts._tcp.example.com') .withSystemName('my-app') .withUseSrv();const configSeedProviderOptions = ConfigSeedProviderOptions.create() .withSeeds(['fallback-1:2552', 'fallback-2:2552']) .withSystemName('my-app');const provider = new AggregateSeedProvider([ new KubernetesApiSeedProvider( kubernetesApiSeedProviderOptions, ), new DnsSeedProvider( dnsSeedProviderOptions, ), new ConfigSeedProvider( configSeedProviderOptions, ),]);
const seeds = await provider.lookup();const clusterOptions = ClusterOptions.create() .withHost(host) .withPort(port) .withSeeds(seeds);await Cluster.join(system, clusterOptions);How it chains
Section titled “How it chains”The provider stops at the first non-empty result. An empty list from one provider triggers fallback to the next; an error also triggers fallback (the error is passed to an optional log callback — a no-op by default).
If every provider fails or returns empty, lookup() resolves
to [] — the cluster’s Cluster.join then either self-bootstraps
or retries (depending on its own settings).
Common patterns
Section titled “Common patterns”Local dev → prod K8s
Section titled “Local dev → prod K8s”const k8sSeedProviderOptions = KubernetesApiSeedProviderOptions.create() .withNamespace(process.env.K8S_NAMESPACE ?? '') .withServiceName('actor-ts') .withSystemName('my-app') .withPort(2552);new AggregateSeedProvider([ seedsFromEnv('ACTOR_TS_SEEDS', 'my-app'), // 1st: env var new KubernetesApiSeedProvider(k8sSeedProviderOptions), // 2nd: K8s API]);Local dev: export ACTOR_TS_SEEDS=localhost:2552 → uses the env
var. In K8s, the env var isn’t set; falls through to the K8s
API.
DNS-first with static fallback
Section titled “DNS-first with static fallback”const dnsSeedProviderOptions = DnsSeedProviderOptions.create() .withHostname('_actor-ts._tcp.example.com') .withSystemName('my-app') .withUseSrv();const configSeedProviderOptions = ConfigSeedProviderOptions.create() .withSeeds(['known-stable-node-1:2552', 'known-stable-node-2:2552']) .withSystemName('my-app');new AggregateSeedProvider([ new DnsSeedProvider( dnsSeedProviderOptions, ), new ConfigSeedProvider( configSeedProviderOptions, ),]);Try DNS first; if it returns empty (DNS server hiccup, no records yet during bootstrapping), use known-stable static IPs.
Multi-region disaster recovery
Section titled “Multi-region disaster recovery”const kubernetesApiSeedProviderOptions = KubernetesApiSeedProviderOptions.create() .withNamespace('primary-region') .withServiceName('actor-ts') .withSystemName('my-app') .withPort(2552);const kubernetesApiSeedProvider2Options = KubernetesApiSeedProviderOptions.create() .withNamespace('failover-region') .withServiceName('actor-ts') .withSystemName('my-app') .withPort(2552);new AggregateSeedProvider([ new KubernetesApiSeedProvider( kubernetesApiSeedProviderOptions, ), new KubernetesApiSeedProvider( kubernetesApiSeedProvider2Options, ),]);In a multi-region deployment, try the local region first; if no pods are running locally, attempt to join the failover region’s cluster. Aggressive — only makes sense if the regions are actually meant to share state.
Error handling
Section titled “Error handling”const kubernetesApiSeedProviderOptions = KubernetesApiSeedProviderOptions.create() .withNamespace('my-app') .withServiceName('actor-ts') .withSystemName('my-app') .withPort(2552);const configSeedProviderOptions = ConfigSeedProviderOptions.create() .withSeeds(['10.0.0.1:2552']) .withSystemName('my-app');new AggregateSeedProvider([ new KubernetesApiSeedProvider( kubernetesApiSeedProviderOptions, ), // raises 403 in non-K8s new ConfigSeedProvider( configSeedProviderOptions, ),]);A 403 from K8s API → skipped → falls through to the config provider. This makes aggregate the right tool for “this code path runs everywhere” — the K8s lookup just becomes a noop where K8s isn’t available.
AggregateSeedProvider takes an optional second constructor
argument — a log callback (message: string, err?: unknown) => void. It defaults to a no-op, so provider errors are silently
swallowed unless you pass one. Supply a log function to get
visibility into which providers tried + failed:
new AggregateSeedProvider( [ new KubernetesApiSeedProvider(kubernetesApiSeedProviderOptions), new ConfigSeedProvider(configSeedProviderOptions), ], (message, error) => console.warn(`[seed] ${message}`, error),);Ordering matters
Section titled “Ordering matters”The first provider that returns a non-empty result is used. Test the order explicitly:
| Order | Effect |
|---|---|
| K8s, then DNS | K8s wins in K8s deployments; DNS is the fallback. |
| DNS, then K8s | DNS wins everywhere; K8s only fires when DNS is unreachable. |
Put the preferred provider first; the fallback last.
Where to next
Section titled “Where to next”- Discovery overview — the bigger picture.
- Config seed provider — static-list provider commonly used as fallback.
- DNS seed provider — the DNS-based provider.
- Kubernetes API seed provider — the K8s-based provider.
- Joining and seeds — how the result is used.
