Skip to content

Commit ed23c48

Browse files
committed
Fix typo and improve Sentinel docs
1 parent 5295926 commit ed23c48

File tree

4 files changed

+104
-22
lines changed

4 files changed

+104
-22
lines changed

docs/sentinel.md

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const sentinel = await createSentinel({
1414
port: 1234
1515
}]
1616
})
17-
.on('error', err => console.error('Redis Sentinel Error', err));
17+
.on('error', err => console.error('Redis Sentinel Error', err))
1818
.connect();
1919

2020
await sentinel.set('key', 'value');
@@ -26,16 +26,19 @@ In the above example, we configure the sentinel object to fetch the configuratio
2626

2727
## `createSentinel` configuration
2828

29-
| Property | Default | Description |
30-
|-----------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
31-
| name | | The sentinel identifier for a particular database cluster |
32-
| sentinelRootNodes | | An array of root nodes that are part of the sentinel cluster, which will be used to get the topology. Each element in the array is a client configuration object. There is no need to specify every node in the cluster: 3 should be enough to reliably connect and obtain the sentinel configuration from the server |
33-
| maxCommandRediscovers | `16` | The maximum number of times a command will retry due to topology changes. |
34-
| nodeClientOptions | | The configuration values for every node in the cluster. Use this for example when specifying an ACL user to connect with |
35-
| sentinelClientOptions | | The configuration values for every sentinel in the cluster. Use this for example when specifying an ACL user to connect with |
36-
| masterPoolSize | `1` | The number of clients connected to the master node |
37-
| replicaPoolSize | `0` | The number of clients connected to each replica node. When greater than 0, the client will distribute the load by executing read-only commands (such as `GET`, `GEOSEARCH`, etc.) across all the cluster nodes. |
38-
| reserveClient | `false` | When `true`, one client will be reserved for the sentinel object. When `false`, the sentinel object will wait for the first available client from the pool. |
29+
| Property | Default | Description |
30+
|----------------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
31+
| name | | The sentinel identifier for a particular database cluster |
32+
| sentinelRootNodes | | An array of root nodes that are part of the sentinel cluster, which will be used to get the topology. Each element in the array is a client configuration object. There is no need to specify every node in the cluster: 3 should be enough to reliably connect and obtain the sentinel configuration from the server |
33+
| maxCommandRediscovers | `16` | The maximum number of times a command will retry due to topology changes. |
34+
| nodeClientOptions | | The configuration values for every node in the cluster. Use this for example when specifying an ACL user to connect with |
35+
| sentinelClientOptions | | The configuration values for every sentinel in the cluster. Use this for example when specifying an ACL user to connect with |
36+
| masterPoolSize | `1` | The number of clients connected to the master node |
37+
| replicaPoolSize | `0` | The number of clients connected to each replica node. When greater than 0, the client will distribute the load by executing read-only commands (such as `GET`, `GEOSEARCH`, etc.) across all the cluster nodes. |
38+
| scanInterval | `10000` | Interval in milliseconds to periodically scan for changes in the sentinel topology. The client will query the sentinel for changes at this interval. |
39+
| passthroughClientErrorEvents | `false` | When `true`, error events from client instances inside the sentinel will be propagated to the sentinel instance. This allows handling all client errors through a single error handler on the sentinel instance. |
40+
| reserveClient | `false` | When `true`, one client will be reserved for the sentinel object. When `false`, the sentinel object will wait for the first available client from the pool. |
41+
3942
## PubSub
4043

4144
It supports PubSub via the normal mechanisms, including migrating the listeners if the node they are connected to goes down.
@@ -60,7 +63,7 @@ createSentinel({
6063
});
6164
```
6265

63-
In addition, it also provides the ability have a pool of clients connected to the replica nodes, and to direct all read-only commands to them:
66+
In addition, it also provides the ability have a pool of clients connected to the replica nodes, and to direct all read-only commands to them:
6467

6568
```javascript
6669
createSentinel({
@@ -85,9 +88,9 @@ const result = await sentinel.use(async client => {
8588
});
8689
```
8790

88-
`.getMasterClientLease()`
91+
`.acquire()`
8992
```javascript
90-
const clientLease = await sentinel.getMasterClientLease();
93+
const clientLease = await sentinel.acquire();
9194

9295
try {
9396
await clientLease.watch('key');

packages/client/lib/sentinel/index.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ async function steadyState(frame: SentinelFramework) {
488488
sentinel.on("error", () => { });
489489
await sentinel.connect();
490490

491-
const clientLease = await sentinel.aquire();
491+
const clientLease = await sentinel.acquire();
492492
clientLease.set('x', 456);
493493

494494
let matched = false;
@@ -554,7 +554,7 @@ async function steadyState(frame: SentinelFramework) {
554554
sentinel = frame.getSentinelClient({ masterPoolSize: 2 });
555555
await sentinel.connect();
556556

557-
const leasedClient = await sentinel.aquire();
557+
const leasedClient = await sentinel.acquire();
558558
await leasedClient.set('x', 1);
559559
await leasedClient.watch('x');
560560
assert.deepEqual(await leasedClient.multi().get('x').exec(), ['1'])
@@ -630,8 +630,8 @@ async function steadyState(frame: SentinelFramework) {
630630

631631
tracer.push("connected");
632632

633-
const client = await sentinel.aquire();
634-
tracer.push("aquired lease");
633+
const client = await sentinel.acquire();
634+
tracer.push("acquired lease");
635635

636636
await client.set("x", 1);
637637
await client.watch("x");
@@ -678,7 +678,7 @@ async function steadyState(frame: SentinelFramework) {
678678
await sentinel.connect();
679679
tracer.push("connected");
680680

681-
const client = await sentinel.aquire();
681+
const client = await sentinel.acquire();
682682
tracer.push("got leased client");
683683
await client.set("x", 1);
684684
await client.watch("x");

packages/client/lib/sentinel/index.ts

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,30 @@ export class RedisSentinelClient<
3232
#internal: RedisSentinelInternal<M, F, S, RESP, TYPE_MAPPING>;
3333
readonly _self: RedisSentinelClient<M, F, S, RESP, TYPE_MAPPING>;
3434

35+
/**
36+
* Indicates if the client connection is open
37+
*
38+
* @returns `true` if the client connection is open, `false` otherwise
39+
*/
40+
3541
get isOpen() {
3642
return this._self.#internal.isOpen;
3743
}
3844

45+
/**
46+
* Indicates if the client connection is ready to accept commands
47+
*
48+
* @returns `true` if the client connection is ready, `false` otherwise
49+
*/
3950
get isReady() {
4051
return this._self.#internal.isReady;
4152
}
4253

54+
/**
55+
* Gets the command options configured for this client
56+
*
57+
* @returns The command options for this client or `undefined` if none were set
58+
*/
4359
get commandOptions() {
4460
return this._self.#commandOptions;
4561
}
@@ -222,6 +238,16 @@ export class RedisSentinelClient<
222238

223239
unwatch = this.UNWATCH;
224240

241+
/**
242+
* Releases the client lease back to the pool
243+
*
244+
* After calling this method, the client instance should no longer be used as it
245+
* will be returned to the client pool and may be given to other operations.
246+
*
247+
* @returns A promise that resolves when the client is ready to be reused, or undefined
248+
* if the client was immediately ready
249+
* @throws Error if the lease has already been released
250+
*/
225251
release() {
226252
if (this._self.#clientInfo === undefined) {
227253
throw new Error('RedisSentinelClient lease already released');
@@ -245,10 +271,20 @@ export default class RedisSentinel<
245271
#internal: RedisSentinelInternal<M, F, S, RESP, TYPE_MAPPING>;
246272
#options: RedisSentinelOptions<M, F, S, RESP, TYPE_MAPPING>;
247273

274+
/**
275+
* Indicates if the sentinel connection is open
276+
*
277+
* @returns `true` if the sentinel connection is open, `false` otherwise
278+
*/
248279
get isOpen() {
249280
return this._self.#internal.isOpen;
250281
}
251282

283+
/**
284+
* Indicates if the sentinel connection is ready to accept commands
285+
*
286+
* @returns `true` if the sentinel connection is ready, `false` otherwise
287+
*/
252288
get isReady() {
253289
return this._self.#internal.isReady;
254290
}
@@ -508,7 +544,28 @@ export default class RedisSentinel<
508544

509545
pUnsubscribe = this.PUNSUBSCRIBE;
510546

511-
async aquire(): Promise<RedisSentinelClientType<M, F, S, RESP, TYPE_MAPPING>> {
547+
/**
548+
* Acquires a master client lease for exclusive operations
549+
*
550+
* Used when multiple commands need to run on an exclusive client (for example, using `WATCH/MULTI/EXEC`).
551+
* The returned client must be released after use with the `release()` method.
552+
*
553+
* @returns A promise that resolves to a Redis client connected to the master node
554+
* @example
555+
* ```javascript
556+
* const clientLease = await sentinel.acquire();
557+
*
558+
* try {
559+
* await clientLease.watch('key');
560+
* const resp = await clientLease.multi()
561+
* .get('key')
562+
* .exec();
563+
* } finally {
564+
* clientLease.release();
565+
* }
566+
* ```
567+
*/
568+
async acquire(): Promise<RedisSentinelClientType<M, F, S, RESP, TYPE_MAPPING>> {
512569
const clientInfo = await this._self.#internal.getClientLease();
513570
return RedisSentinelClient.create(this._self.#options, this._self.#internal, clientInfo, this._self.#commandOptions);
514571
}
@@ -638,6 +695,12 @@ class RedisSentinelInternal<
638695
});
639696
}
640697

698+
/**
699+
* Gets a client lease from the master client pool
700+
*
701+
* @returns A client info object or a promise that resolves to a client info object
702+
* when a client becomes available
703+
*/
641704
getClientLease(): ClientInfo | Promise<ClientInfo> {
642705
const id = this.#masterClientQueue.shift();
643706
if (id !== undefined) {
@@ -647,6 +710,16 @@ class RedisSentinelInternal<
647710
return this.#masterClientQueue.wait().then(id => ({ id }));
648711
}
649712

713+
/**
714+
* Releases a client lease back to the pool
715+
*
716+
* If the client was used for a transaction that might have left it in a dirty state,
717+
* it will be reset before being returned to the pool.
718+
*
719+
* @param clientInfo The client info object representing the client to release
720+
* @returns A promise that resolves when the client is ready to be reused, or undefined
721+
* if the client was immediately ready or no longer exists
722+
*/
650723
releaseClientLease(clientInfo: ClientInfo) {
651724
const client = this.#masterClients[clientInfo.id];
652725
// client can be undefined if releasing in middle of a reconfigure

packages/client/lib/sentinel/types.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,17 @@ export interface RedisSentinelOptions<
4949
*/
5050
replicaPoolSize?: number;
5151
/**
52-
* TODO
52+
* Interval in milliseconds to periodically scan for changes in the sentinel topology.
53+
* The client will query the sentinel for changes at this interval.
54+
*
55+
* Default: 10000 (10 seconds)
5356
*/
5457
scanInterval?: number;
5558
/**
56-
* TODO
59+
* When `true`, error events from client instances inside the sentinel will be propagated to the sentinel instance.
60+
* This allows handling all client errors through a single error handler on the sentinel instance.
61+
*
62+
* Default: false
5763
*/
5864
passthroughClientErrorEvents?: boolean;
5965
/**

0 commit comments

Comments
 (0)