Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds redis cluster support via a ClusterService and ClusterModule #51

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
541 changes: 400 additions & 141 deletions README.md

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions dist/cluster-core.module.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DynamicModule, OnModuleDestroy } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { RedisClusterModuleAsyncOptions, RedisClusterModuleOptions } from './cluster.interface';
export declare class ClusterCoreModule implements OnModuleDestroy {
private readonly options;
private readonly moduleRef;
constructor(options: RedisClusterModuleOptions | RedisClusterModuleOptions[], moduleRef: ModuleRef);
static register(options: RedisClusterModuleOptions | RedisClusterModuleOptions[]): DynamicModule;
static forRootAsync(options: RedisClusterModuleAsyncOptions): DynamicModule;
onModuleDestroy(): void;
}
72 changes: 72 additions & 0 deletions dist/cluster-core.module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var ClusterCoreModule_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClusterCoreModule = void 0;
const common_1 = require("@nestjs/common");
const core_1 = require("@nestjs/core");
const cluster_provider_1 = require("./cluster.provider");
const cluster_constants_1 = require("./cluster.constants");
const cluster_service_1 = require("./cluster.service");
let ClusterCoreModule = ClusterCoreModule_1 = class ClusterCoreModule {
constructor(options, moduleRef) {
this.options = options;
this.moduleRef = moduleRef;
}
static register(options) {
return {
module: ClusterCoreModule_1,
providers: [
cluster_provider_1.createCluster(),
{ provide: cluster_constants_1.REDIS_CLUSTER_MODULE_OPTIONS, useValue: options },
],
exports: [cluster_service_1.RedisClusterService],
};
}
static forRootAsync(options) {
return {
module: ClusterCoreModule_1,
imports: options.imports,
providers: [cluster_provider_1.createCluster(), cluster_provider_1.createAsyncClusterOptions(options)],
exports: [cluster_service_1.RedisClusterService],
};
}
onModuleDestroy() {
const closeConnection = ({ clusters, defaultKey, }) => options => {
const name = options.name || defaultKey;
const cluster = clusters.get(name);
if (cluster && !options.keepAlive) {
cluster.disconnect();
}
};
const provider = this.moduleRef.get(cluster_constants_1.REDIS_CLUSTER);
const closeClusterConnection = closeConnection(provider);
if (Array.isArray(this.options)) {
this.options.forEach(closeClusterConnection);
}
else {
closeClusterConnection(this.options);
}
}
};
ClusterCoreModule = ClusterCoreModule_1 = __decorate([
common_1.Global(),
common_1.Module({
providers: [cluster_service_1.RedisClusterService],
exports: [cluster_service_1.RedisClusterService],
}),
__param(0, common_1.Inject(cluster_constants_1.REDIS_CLUSTER_MODULE_OPTIONS)),
__metadata("design:paramtypes", [Object, core_1.ModuleRef])
], ClusterCoreModule);
exports.ClusterCoreModule = ClusterCoreModule;
2 changes: 2 additions & 0 deletions dist/cluster.constants.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export declare const REDIS_CLUSTER_MODULE_OPTIONS: unique symbol;
export declare const REDIS_CLUSTER: unique symbol;
5 changes: 5 additions & 0 deletions dist/cluster.constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.REDIS_CLUSTER = exports.REDIS_CLUSTER_MODULE_OPTIONS = void 0;
exports.REDIS_CLUSTER_MODULE_OPTIONS = Symbol('REDIS_CLUSTER_MODULE_OPTIONS');
exports.REDIS_CLUSTER = Symbol('REDIS_CLUSTER');
11 changes: 11 additions & 0 deletions dist/cluster.interface.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ModuleMetadata } from '@nestjs/common/interfaces';
import { Redis, ClusterOptions } from 'ioredis';
export interface RedisClusterModuleOptions extends ClusterOptions {
name?: string;
nodes: (string | number | object)[];
onClusterReady?(cluster: Redis): Promise<void>;
}
export interface RedisClusterModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
useFactory?: (...args: any[]) => RedisClusterModuleOptions | RedisClusterModuleOptions[] | Promise<RedisClusterModuleOptions> | Promise<RedisClusterModuleOptions[]>;
inject?: any[];
}
2 changes: 2 additions & 0 deletions dist/cluster.interface.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
6 changes: 6 additions & 0 deletions dist/cluster.module.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { DynamicModule } from '@nestjs/common';
import { RedisClusterModuleAsyncOptions, RedisClusterModuleOptions } from './cluster.interface';
export declare class RedisClusterModule {
static register(options: RedisClusterModuleOptions | RedisClusterModuleOptions[]): DynamicModule;
static forRootAsync(options: RedisClusterModuleAsyncOptions): DynamicModule;
}
30 changes: 30 additions & 0 deletions dist/cluster.module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var RedisClusterModule_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisClusterModule = void 0;
const common_1 = require("@nestjs/common");
const cluster_core_module_1 = require("./cluster-core.module");
let RedisClusterModule = RedisClusterModule_1 = class RedisClusterModule {
static register(options) {
return {
module: RedisClusterModule_1,
imports: [cluster_core_module_1.ClusterCoreModule.register(options)],
};
}
static forRootAsync(options) {
return {
module: RedisClusterModule_1,
imports: [cluster_core_module_1.ClusterCoreModule.forRootAsync(options)],
};
}
};
RedisClusterModule = RedisClusterModule_1 = __decorate([
common_1.Module({})
], RedisClusterModule);
exports.RedisClusterModule = RedisClusterModule;
16 changes: 16 additions & 0 deletions dist/cluster.provider.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Redis } from 'ioredis';
import { Provider } from '@nestjs/common';
import { RedisClusterModuleAsyncOptions, RedisClusterModuleOptions } from './cluster.interface';
export declare class RedisClusterError extends Error {
}
export interface RedisClusterProvider {
defaultKey: string;
clusters: Map<string, Redis>;
size: number;
}
export declare const createCluster: () => Provider;
export declare const createAsyncClusterOptions: (options: RedisClusterModuleAsyncOptions) => {
provide: symbol;
useFactory: (...args: any[]) => RedisClusterModuleOptions | Promise<RedisClusterModuleOptions> | RedisClusterModuleOptions[] | Promise<RedisClusterModuleOptions[]>;
inject: any[];
};
72 changes: 72 additions & 0 deletions dist/cluster.provider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createAsyncClusterOptions = exports.createCluster = exports.RedisClusterError = void 0;
const ioredis_1 = require("ioredis");
const uuid = require("uuid");
const cluster_constants_1 = require("./cluster.constants");
class RedisClusterError extends Error {
}
exports.RedisClusterError = RedisClusterError;
function getCluster(options) {
return __awaiter(this, void 0, void 0, function* () {
const { onClusterReady, nodes } = options, opt = __rest(options, ["onClusterReady", "nodes"]);
const cluster = new ioredis_1.Cluster(nodes, opt);
if (onClusterReady) {
onClusterReady(cluster);
}
return cluster;
});
}
exports.createCluster = () => ({
provide: cluster_constants_1.REDIS_CLUSTER,
useFactory: (options) => __awaiter(void 0, void 0, void 0, function* () {
const clusters = new Map();
let defaultKey = uuid();
if (Array.isArray(options)) {
yield Promise.all(options.map((o) => __awaiter(void 0, void 0, void 0, function* () {
const key = o.name || defaultKey;
if (clusters.has(key)) {
throw new RedisClusterError(`${o.name || 'default'} cluster already exists`);
}
clusters.set(key, yield getCluster(o));
})));
}
else {
if (options.name && options.name.length !== 0) {
defaultKey = options.name;
}
clusters.set(defaultKey, yield getCluster(options));
}
return {
defaultKey,
clusters,
size: clusters.size,
};
}),
inject: [cluster_constants_1.REDIS_CLUSTER_MODULE_OPTIONS],
});
exports.createAsyncClusterOptions = (options) => ({
provide: cluster_constants_1.REDIS_CLUSTER_MODULE_OPTIONS,
useFactory: options.useFactory,
inject: options.inject,
});
8 changes: 8 additions & 0 deletions dist/cluster.service.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Redis } from 'ioredis';
import { RedisClusterProvider } from './cluster.provider';
export declare class RedisClusterService {
private readonly provider;
constructor(provider: RedisClusterProvider);
getCluster(name?: string): Redis;
getClusters(): Map<string, Redis>;
}
41 changes: 41 additions & 0 deletions dist/cluster.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisClusterService = void 0;
const common_1 = require("@nestjs/common");
const cluster_constants_1 = require("./cluster.constants");
const cluster_provider_1 = require("./cluster.provider");
let RedisClusterService = class RedisClusterService {
constructor(provider) {
this.provider = provider;
}
getCluster(name) {
if (!name) {
name = this.provider.defaultKey;
}
if (!this.provider.clusters.has(name)) {
throw new cluster_provider_1.RedisClusterError(`cluster ${name} does not exist`);
}
return this.provider.clusters.get(name);
}
getClusters() {
return this.provider.clusters;
}
};
RedisClusterService = __decorate([
common_1.Injectable(),
__param(0, common_1.Inject(cluster_constants_1.REDIS_CLUSTER)),
__metadata("design:paramtypes", [Object])
], RedisClusterService);
exports.RedisClusterService = RedisClusterService;
3 changes: 3 additions & 0 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export * from './redis.service';
export * from './redis.module';
export * from './redis.interface';
export * from './cluster.service';
export * from './cluster.module';
export * from './cluster.interface';
21 changes: 16 additions & 5 deletions dist/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__export(require("./redis.service"));
__export(require("./redis.module"));
__exportStar(require("./redis.service"), exports);
__exportStar(require("./redis.module"), exports);
__exportStar(require("./redis.interface"), exports);
__exportStar(require("./cluster.service"), exports);
__exportStar(require("./cluster.module"), exports);
__exportStar(require("./cluster.interface"), exports);
9 changes: 5 additions & 4 deletions dist/redis-core.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ var __metadata = (this && this.__metadata) || function (k, v) {
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
var RedisCoreModule_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisCoreModule = void 0;
const common_1 = require("@nestjs/common");
const core_1 = require("@nestjs/core");
const redis_client_provider_1 = require("./redis-client.provider");
const redis_provider_1 = require("./redis.provider");
const redis_constants_1 = require("./redis.constants");
const redis_service_1 = require("./redis.service");
let RedisCoreModule = RedisCoreModule_1 = class RedisCoreModule {
Expand All @@ -27,7 +28,7 @@ let RedisCoreModule = RedisCoreModule_1 = class RedisCoreModule {
return {
module: RedisCoreModule_1,
providers: [
redis_client_provider_1.createClient(),
redis_provider_1.createClient(),
{ provide: redis_constants_1.REDIS_MODULE_OPTIONS, useValue: options },
],
exports: [redis_service_1.RedisService],
Expand All @@ -37,7 +38,7 @@ let RedisCoreModule = RedisCoreModule_1 = class RedisCoreModule {
return {
module: RedisCoreModule_1,
imports: options.imports,
providers: [redis_client_provider_1.createClient(), redis_client_provider_1.createAsyncClientOptions(options)],
providers: [redis_provider_1.createClient(), redis_provider_1.createAsyncClientOptions(options)],
exports: [redis_service_1.RedisService],
};
}
Expand Down
1 change: 1 addition & 0 deletions dist/redis.constants.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.REDIS_CLIENT = exports.REDIS_MODULE_OPTIONS = void 0;
exports.REDIS_MODULE_OPTIONS = Symbol('REDIS_MODULE_OPTIONS');
exports.REDIS_CLIENT = Symbol('REDIS_CLIENT');
3 changes: 2 additions & 1 deletion dist/redis.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
var RedisModule_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisModule = void 0;
const common_1 = require("@nestjs/common");
const redis_core_module_1 = require("./redis-core.module");
let RedisModule = RedisModule_1 = class RedisModule {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface RedisClient {
clients: Map<string, Redis.Redis>;
size: number;
}
export declare const createClient: () => Provider<any>;
export declare const createClient: () => Provider;
export declare const createAsyncClientOptions: (options: RedisModuleAsyncOptions) => {
provide: symbol;
useFactory: (...args: any[]) => RedisModuleOptions | Promise<RedisModuleOptions> | RedisModuleOptions[] | Promise<RedisModuleOptions[]>;
Expand Down
Loading