Skip to content

Commit

Permalink
docs: update (#224)
Browse files Browse the repository at this point in the history
  • Loading branch information
liaoliaots committed Mar 28, 2022
1 parent 8cc7a25 commit 1111be1
Show file tree
Hide file tree
Showing 6 changed files with 1,661 additions and 3 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,23 @@ Redis(<a href="https://github.com/luin/ioredis">ioredis</a>) module for NestJS f

- v5, [click here](docs/v5)
- v6, [click here](docs/v6)
- v7, [click here](docs/v7)

## Prerequisites

- [node](https://nodejs.org/en/) >=12.22.0
- [ioredis](https://github.com/luin/ioredis) 5.x

## Install

**This package supports both nestjs 7.x and 8.x**.

```sh
$ npm install --save @liaoliaots/nestjs-redis ioredis
$ npm install --save-dev @types/ioredis
```

```sh
$ yarn add @liaoliaots/nestjs-redis ioredis
$ yarn add --dev @types/ioredis
```

## Test a class
Expand All @@ -85,7 +89,7 @@ This package exports `getRedisToken()` and `getClusterToken()` functions that re

```TypeScript
const module: TestingModule = await Test.createTestingModule({
providers: [{ provide: getRedisToken('your namespace'), useValue: mockClient }, YourService]
providers: [{ provide: getRedisToken('namespace'), useValue: mockedClient }, YourService]
}).compile();
```

Expand Down
348 changes: 348 additions & 0 deletions docs/v7/cluster.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,348 @@
# Cluster

## Usage

**1**, we need to import the `ClusterModule` into our root module:

```TypeScript
import { Module } from '@nestjs/common';
import { ClusterModule } from '@liaoliaots/nestjs-redis';

@Module({
imports: [
ClusterModule.forRoot({
config: {
nodes: [{ host: 'localhost', port: 16380 }],
redisOptions: { password: 'cluster1' }
}
})
]
})
export class AppModule {}
```

> HINT: The `ClusterModule` is a [global module](https://docs.nestjs.com/modules#global-modules). Once defined, this module is available everywhere.
**2**, we can use cluster in two ways.

via decorator:

```TypeScript
import { Injectable } from '@nestjs/common';
import { InjectCluster, DEFAULT_CLUSTER_NAMESPACE } from '@liaoliaots/nestjs-redis';
import { Cluster } from 'ioredis';

@Injectable()
export class AppService {
constructor(
@InjectCluster() private readonly cluster: Cluster
// or
// @InjectCluster(DEFAULT_CLUSTER_NAMESPACE) private readonly cluster: Cluster
) {}

async ping(): Promise<string> {
return await this.cluster.ping();
}
}
```

via service:

```TypeScript
import { Injectable } from '@nestjs/common';
import { ClusterService, DEFAULT_CLUSTER_NAMESPACE } from '@liaoliaots/nestjs-redis';
import { Cluster } from 'ioredis';

@Injectable()
export class AppService {
private readonly cluster: Cluster;

constructor(private readonly clusterService: ClusterService) {
this.cluster = this.clusterService.getClient();
// or
// this.cluster = this.clusterService.getClient(DEFAULT_CLUSTER_NAMESPACE);
}

async ping(): Promise<string> {
return await this.cluster.ping();
}
}
```

> HINT: If you don't set the namespace for a client, its namespace is set to default. Please note that you shouldn't have multiple client without a namespace, or with the same namespace, otherwise they will get overridden.
## Configuration

### ClusterModuleOptions

| Name | Type | Default value | Description |
| ----------- | ------------------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| closeClient | boolean | true | If `true`, all clients will be closed automatically on nestjs application shutdown. To use `closeClient`, you **must enable listeners** by calling `app.enableShutdownHooks()`. [Read more about the application shutdown.](https://docs.nestjs.com/fundamentals/lifecycle-events#application-shutdown) |
| readyLog | boolean | false | If `true`, will show a message when the client is ready. |
| config | `ClientOptions` or `ClientOptions`[] | undefined | Specify single or multiple clients. |

### ClientOptions

| Name | Type | Default value | Description |
| ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------- |
| namespace | string or symbol | 'default' | The name of the client, and must be unique. You can import `DEFAULT_CLUSTER_NAMESPACE` to reference the default value. |
| [nodes](https://github.com/luin/ioredis/blob/master/API.md#new-clusterstartupnodes-options) | `{ host?: string; port?: number }[]` or `string[]` or `number[]` | undefined | A list of nodes of the cluster. The **first** argument of `new Cluster(startupNodes, options).` |
| onClientCreated | function | undefined | This function will be executed as soon as the client is created. |
| **...**[ClusterOptions](https://github.com/luin/ioredis/blob/v4/API.md#new-clusterstartupnodes-options) | object | - | Extends the [ClusterOptions](https://github.com/luin/ioredis/blob/v4/lib/cluster/ClusterOptions.ts#L30). |

### Asynchronous configuration

via `useFactory`:

```TypeScript
import { Module } from '@nestjs/common';
import { ClusterModule, ClusterModuleOptions } from '@liaoliaots/nestjs-redis';
import { ConfigService, ConfigModule } from '@nestjs/config';

@Module({
imports: [
ClusterModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService): Promise<ClusterModuleOptions> => {
await somePromise();

return {
config: {
nodes: [{ host: 'localhost', port: 16380 }],
redisOptions: { password: 'cluster1' }
}
};
}
})
]
})
export class AppModule {}
```

via `useClass`:

```TypeScript
import { Module, Injectable } from '@nestjs/common';
import { ClusterModule, ClusterOptionsFactory, ClusterModuleOptions } from '@liaoliaots/nestjs-redis';

@Injectable()
export class ClusterConfigService implements ClusterOptionsFactory {
async createClusterOptions(): Promise<ClusterModuleOptions> {
await somePromise();

return {
config: {
nodes: [{ host: 'localhost', port: 16380 }],
redisOptions: { password: 'cluster1' }
}
};
}
}

@Module({
imports: [
ClusterModule.forRootAsync({
useClass: ClusterConfigService
})
]
})
export class AppModule {}
```

via `extraProviders`:

```TypeScript
// just a simple example

import { Module, ValueProvider } from '@nestjs/common';
import { ClusterModule, ClusterModuleOptions } from '@liaoliaots/nestjs-redis';

const MyOptionsSymbol = Symbol('options');
const MyOptionsProvider: ValueProvider<ClusterModuleOptions> = {
provide: MyOptionsSymbol,
useValue: {
readyLog: true,
config: {
nodes: [{ host: 'localhost', port: 16380 }],
redisOptions: { password: 'cluster1' }
}
}
};

@Module({
imports: [
ClusterModule.forRootAsync({
useFactory(options: ClusterModuleOptions) {
return options;
},
inject: [MyOptionsSymbol],
extraProviders: [MyOptionsProvider]
})
]
})
export class AppModule {}
```

... or via `useExisting`, if you wish to use an existing configuration provider imported from a different module.

```TypeScript
ClusterModule.forRootAsync({
imports: [ConfigModule],
useExisting: ConfigService
})
```

### readyLog

```TypeScript
import { Module } from '@nestjs/common';
import { ClusterModule } from '@liaoliaots/nestjs-redis';

@Module({
imports: [
ClusterModule.forRoot({
readyLog: true,
config: {
nodes: [{ host: 'localhost', port: 16380 }],
redisOptions: { password: 'cluster1' }
}
})
]
})
export class AppModule {}
```

The `ClusterModule` will display a message when `CLUSTER INFO` reporting the cluster is able to receive commands.

```sh
[Nest] 18886 - 09/16/2021, 6:19:56 PM LOG [ClusterModule] default: Connected successfully to the server
```

### Single client

```TypeScript
import { Module } from '@nestjs/common';
import { ClusterModule } from '@liaoliaots/nestjs-redis';

@Module({
imports: [
ClusterModule.forRoot({
config: {
nodes: [{ host: 'localhost', port: 16380 }],
redisOptions: { password: 'cluster1' }

// or with URL
// nodes: ['redis://:cluster1@localhost:16380']
}
})
]
})
export class AppModule {}
```

### Multiple clients

```TypeScript
import { Module } from '@nestjs/common';
import { ClusterModule } from '@liaoliaots/nestjs-redis';

@Module({
imports: [
ClusterModule.forRoot({
config: [
{
nodes: [{ host: 'localhost', port: 16380 }],
redisOptions: { password: 'cluster1' }
},
{
namespace: 'cluster2',
nodes: [{ host: 'localhost', port: 16480 }],
redisOptions: { password: 'cluster2' }
}
]
})
]
})
export class AppModule {}
```

with URL:

```TypeScript
import { Module } from '@nestjs/common';
import { ClusterModule } from '@liaoliaots/nestjs-redis';

@Module({
imports: [
ClusterModule.forRoot({
config: [
{
nodes: ['redis://:cluster1@localhost:16380']
},
{
namespace: 'cluster2',
nodes: ['redis://:cluster2@localhost:16480']
}
]
})
]
})
export class AppModule {}
```

### onClientCreated

For example, we can listen to the error event of the cluster client.

```TypeScript
import { Module } from '@nestjs/common';
import { ClusterModule } from '@liaoliaots/nestjs-redis';

@Module({
imports: [
ClusterModule.forRoot({
config: {
nodes: [{ host: 'localhost', port: 16380 }],
redisOptions: { password: 'cluster1' },
onClientCreated(client) {
client.on('error', err => {});
}
}
})
]
})
export class AppModule {}
```

### Non-global

By default, the `ClusterModule` is registered in the global scope, so `ClusterService` and `all cluster clients defined` are available everywhere.

You can change the behavior by modifying `isGlobal` parameter:

```TypeScript
// cats.module.ts
import { Module } from '@nestjs/common';
import { ClusterModule } from '@liaoliaots/nestjs-redis';
import { CatsService } from './cats.service';
import { CatsController } from './cats.controller';

@Module({
imports: [
ClusterModule.forRoot(
{
readyLog: true,
config: {
nodes: [{ host: 'localhost', port: 16380 }],
redisOptions: { password: 'cluster1' }
}
},
false // <-- register inside the module scope
)
],
providers: [CatsService],
controllers: [CatsController]
})
export class CatsModule {}
```
Loading

0 comments on commit 1111be1

Please sign in to comment.