/// /// /// import { EventEmitter } from 'events'; import { Namespace } from './namespace'; /** * Object returned from election.observer() that exposees information about * the current election. * @noInheritDoc */ export declare class ElectionObserver extends EventEmitter { private readonly namespace; /** * Gets whether the election has any leader. */ get hasLeader(): boolean; private running; private runLoop; private disposer?; private current; constructor(namespace: Namespace); /** * change is fired when the elected value changes. It can be fired with * undefined if there's no longer a leader. */ on(event: 'change', handler: (value: string | undefined) => void): this; /** * disconnected is fired when the underlying watcher is disconnected. Etcd3 * will automatically attempt to reconnect in the background. This has the * same semantics as the `disconnected` event on the {@link Watcher}. */ on(event: 'disconnected', handler: (value: Error) => void): this; /** * error is fired if the underlying election watcher * experiences an unrecoverable error. */ on(event: 'error', handler: (value: Error) => void): this; /** * Closes the election observer. */ cancel(): Promise; /** * Returns the currently-elected leader value (passed to `campaign()` or * `proclaim()`), or undefined if there's no elected leader. */ leader(encoding?: BufferEncoding): string | undefined; /** * Returns the currently-elected leader value (passed to `campaign()` or * `proclaim()`), or undefined if there's no elected leader. */ leader(encoding: 'buffer'): Buffer | undefined; private setLeader; private loop; } /** * A Campaign is returned from {@link Election.campaign}. See the docs on that * method for an example. * @noInheritDoc */ export declare class Campaign extends EventEmitter { private readonly namespace; private lease; private keyRevision?; private value; private pendingProclaimation?; constructor(namespace: Namespace, value: string | Buffer, ttl: number); /** * elected is fired when the current instance becomes the leader. */ on(event: 'elected', handler: () => void): this; /** * error is fired if the underlying lease experiences an error. When this * is emitted, the campaign has failed. You should handle this and create * a new campaign if appropriate. */ on(event: 'error', handler: (error: Error) => void): this; /** * Helper function that returns a promise when the node becomes the leader. * If `resign()` is called before this happens, the promise never resolves. * If an error is emitted, the promise is rejected. */ wait(): Promise; /** * Updates the value announced by this candidate (without starting a new * election). If this candidate is currently the leader, then the change * will be seen on other consumers as well. * * @throws NotCampaigningError if the instance is no longer campaigning */ proclaim(value: string | Buffer): Promise; /** * Gets the etcd key in which the proclaimed value is stored. This is derived * from the underlying lease, and thus may throw if the lease was not granted * successfully. */ getCampaignKey(): Promise; /** * Resigns from the campaign. A new leader is elected if this instance was * formerly the leader. */ resign(): Promise; private start; private proclaimInner; private waitForElected; } /** * Implementation of elections, as seen in etcd's Go client. Elections are * most commonly used if you need a single server in charge of a certain task; * you run an election on every server where your program is running, and * among them they will choose one "leader". * * There are two main entrypoints: campaigning via {@link Election.campaign}, * and observing the leader via {@link Election.observe}. * * @see https://github.com/etcd-io/etcd/blob/master/client/v3/concurrency/election.go * * @example * * ```js * const os = require('os'); * const client = new Etcd3(); * const election = client.election('singleton-job'); * * function runCampaign() { * const campaign = election.campaign(os.hostname()) * campaign.on('elected', () => { * // This server is now the leader! Let's start doing work * doSomeWork(); * }); * campaign.on('error', error => { * // An error happened that caused our campaign to fail. If we were the * // leader, make sure to stop doing work (another server is the leader * // now) and create a new campaign. * console.error(error); * stopDoingWork(); * setTimeout(runCampaign, 5000); * }); * } * * async function observeLeader() { * const observer = await election.observe(); * console.log('The current leader is', observer.leader()); * observer.on('change', leader => console.log('The new leader is', leader)); * observer.on('error', () => { * // Something happened that fatally interrupted observation. * setTimeout(observeLeader, 5000); * }); * } * ``` * @noInheritDoc */ export declare class Election { readonly name: string; private readonly ttl; /** * Prefix used in the namespace for election-based operations. */ static readonly prefix = "election"; private readonly namespace; /** * @internal */ constructor(parent: Namespace, name: string, ttl?: number); /** * Puts the value as eligible for election. Multiple sessions can participate * in the election, but only one can be the leader at a time. * * A common pattern in cluster-based applications is to campaign the hostname * or IP of the current server, and allow the leader server to be elected * among them. * * You should listen to the `error` and `elected` events on the returned * object to know when the instance becomes the leader, and when its campaign * fails. Once you're finished, you can use {@link Campaign.resign} to * forfeit its bid at leadership. * * Once acquired, instance will not lose its leadership unless `resign()` * is called, or `error` is emitted. */ campaign(value: string): Campaign; /** * Returns the currently-elected leader value (passed to `campaign()` or * `proclaim()`), or undefined if there's no elected leader. */ leader(encoding?: BufferEncoding): Promise; /** * Returns the currently-elected leader value (passed to `campaign()` or * `proclaim()`), or undefined if there's no elected leader. */ leader(encoding: 'buffer'): Promise; /** * Creates an observer for the election, which emits events when results * change. The observer must be closed using `observer.cancel()` when * you're finished with it. */ observe(): Promise; }