github-actions[bot] commented on code in PR #4552:
URL: https://github.com/apache/iggy/pull/4552#discussion_r4283794590
##########
foreign/node/src/client/client.type.ts:
##########
@@ -74,6 +74,20 @@ export type SendCommandOptions = {
context?: PartitionContext
};
+/**
+ * Connection lifecycle events of a `Client`, with their listener arguments.
+ */
+export type ClientEventMap = {
+ /** A dial to the server starts: the first one, a redial or a redirect */
+ connecting: [],
+ /** The dialed socket is ready: TCP connected, or TLS handshake done */
+ connected: [],
+ /** The connection reported an error, such as a failed dial */
+ error: [error: Error],
+ /** `destroy()` closed the connection. No event follows this one */
Review Comment:
warning: `redirect()` checks no `ending` flag. A leader move decided during
`destroy()` therefore installs a socket that nothing closes, and that dial can
report `connected` after `end`. Return early in `redirect()` when `ending` is
set.
##########
foreign/node/src/client/client.ts:
##########
@@ -80,15 +91,77 @@ export class Client extends CommandAPI {
*/
constructor(config: ClientConfigOrString) {
const normalizedConfig = normalizeClientConfig(config);
- const { clientProvider, pool } =
+ const { clientProvider, pool, client } =
createPooledClientProvider(normalizedConfig);
super(clientProvider);
this._config = normalizedConfig;
this._pool = pool;
+ this.events = client;
+ }
+
+ /**
+ * Registers a listener for a connection lifecycle event.
+ *
+ * @param event - Event name
+ * @param listener - Called with the event's arguments
+ * @returns This client
+ */
+ on<E extends keyof ClientEventMap>(
Review Comment:
warning: `SingleClient` and `SimpleClient` get none of the new event
methods, so their users cannot listen for the lifecycle events the README
describes. State the limit in the README, or move the four methods into a
shared base.
##########
foreign/node/README.md:
##########
@@ -128,6 +128,31 @@ const client = new Client({
const stats = await client.system.getStats();
```
+### Connection events
+
+`Client` reports its connection lifecycle through Node.js-style `on`, `once`
Review Comment:
nit: This paragraph lists `on`, `once` and `off` but omits `removeListener`,
which `node:events.once()` uses to drop its listener. Add `removeListener` to
the list.
##########
foreign/node/README.md:
##########
@@ -128,6 +128,31 @@ const client = new Client({
const stats = await client.system.getStats();
```
+### Connection events
+
+`Client` reports its connection lifecycle through Node.js-style `on`, `once`
+and `off` methods. Each method returns the client, so calls can be chained.
+
+```ts
+client
+ .on("connecting", () => console.log("dialing the server"))
+ .once("connected", () => console.log("connected"))
+ .on("error", (error) => console.error("connection error", error))
+ .on("end", () => console.log("client destroyed"));
+```
+
+- `connecting` fires once for each dial: the first one, each redial after
Review Comment:
nit: The first `connecting` goes out on the next tick, so a listener
attached after any `await` misses the first dial. Say in this bullet that the
listener must follow the constructor in the same tick.
##########
foreign/node/src/client/client.ts:
##########
@@ -80,15 +91,77 @@ export class Client extends CommandAPI {
*/
constructor(config: ClientConfigOrString) {
const normalizedConfig = normalizeClientConfig(config);
- const { clientProvider, pool } =
+ const { clientProvider, pool, client } =
createPooledClientProvider(normalizedConfig);
super(clientProvider);
this._config = normalizedConfig;
this._pool = pool;
+ this.events = client;
+ }
+
+ /**
+ * Registers a listener for a connection lifecycle event.
+ *
+ * @param event - Event name
+ * @param listener - Called with the event's arguments
+ * @returns This client
+ */
+ on<E extends keyof ClientEventMap>(
+ event: E,
+ listener: (...args: ClientEventMap[E]) => void
+ ): this {
+ this.events.on(event, listener);
+ return this;
+ }
+
+ /**
+ * Registers a listener that runs on the next occurrence of an event only.
+ *
+ * @param event - Event name
+ * @param listener - Called with the event's arguments
+ * @returns This client
+ */
+ once<E extends keyof ClientEventMap>(
+ event: E,
+ listener: (...args: ClientEventMap[E]) => void
+ ): this {
+ this.events.once(event, listener);
+ return this;
+ }
+
+ /**
+ * Removes a listener registered with `on` or `once`.
+ *
+ * @param event - Event name
+ * @param listener - The listener to remove
+ * @returns This client
+ */
+ off<E extends keyof ClientEventMap>(
+ event: E,
+ listener: (...args: ClientEventMap[E]) => void
+ ): this {
+ this.events.off(event, listener);
+ return this;
+ }
+
+ /**
+ * Alias of `off`. At run time, `events.once()` and `events.on()` from
+ * `node:events` remove their listeners through this name.
+ *
+ * @param event - Event name
+ * @param listener - The listener to remove
+ * @returns This client
+ */
+ removeListener<E extends keyof ClientEventMap>(
+ event: E,
+ listener: (...args: ClientEventMap[E]) => void
+ ): this {
+ return this.off(event, listener);
}
/**
* Destroys the client and drains all connections from the pool.
+ * Resolves after the 'end' event.
Review Comment:
warning: `SingleClient.destroy()` and `SimpleClient.destroy()` drop the
promise, and `RawClient.destroy` is still typed `() => void`, so only `Client`
waits for `end`. Await the promise in both methods, or narrow this line to
`Client`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]