Skip to content

Commit

Permalink
Add generics
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitryuk committed Jan 2, 2021
1 parent 64d7f59 commit 689ee8f
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 40 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Redis functions balancer
[![NPM](https://nodei.co/npm/redis-functions-balancer.png)](https://nodei.co/npm/redis-functions-balancer/)

Balance executable NodeJs function with redis.
Balance executes of NodeJs-functions with redis.

For example, if you have several functions (A, B, C) doing the same things (http requests, long-running code), and you want to execute it evenly.

Expand Down Expand Up @@ -37,14 +37,14 @@ let iterator = await balancer.getAsyncIterator();

while ( (foo = await iterator.next()) && !foo.done) {
// Your function A|B|C will be here evenly
let method = foo.value;
let func = foo.value;

try {
// Executing on your way (
foo.value();
func();
} catch (e) {
// something happen badly and you want to postpone executes of the function next 10 runs
balancer.increaseMethodRank(method, 10);
balancer.increaseRank(func, 10);
}
}

Expand Down
26 changes: 13 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ var __spreadArrays = (this && this.__spreadArrays) || function () {
};
Object.defineProperty(exports, "__esModule", { value: true });
var util_1 = require("util");
var CallableBalancer = /** @class */ (function () {
var RedisFunctionsBalancer = /** @class */ (function () {
/**
*
* @param methods not empty array of functions
* @param redisClient
*/
function CallableBalancer(methods, redisClient) {
function RedisFunctionsBalancer(methods, redisClient) {
this._STORE_PREFIX = 'balancer';
this.INC_VALUE = 1;
this._redisClient = redisClient;
Expand All @@ -76,24 +76,24 @@ var CallableBalancer = /** @class */ (function () {
zIncRbyAsync: util_1.promisify(redisClient.zincrby).bind(this._redisClient),
};
}
CallableBalancer.prototype.setMethods = function (methods) {
RedisFunctionsBalancer.prototype.setMethods = function (methods) {
this._methods = methods;
this._storeKey = this.makeStoreKey(methods);
};
CallableBalancer.prototype.increaseMethodRank = function (method, incValue) {
RedisFunctionsBalancer.prototype.increaseRank = function (func, incValue) {
if (incValue === void 0) { incValue = this.INC_VALUE; }
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._functions.zIncRbyAsync(this._storeKey, incValue, method.name)];
case 0: return [4 /*yield*/, this._functions.zIncRbyAsync(this._storeKey, incValue, func.name)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
CallableBalancer.prototype.getAsyncIterator = function () {
RedisFunctionsBalancer.prototype.getAsyncIterator = function () {
return __asyncGenerator(this, arguments, function getAsyncIterator_1() {
var storedMethodNames, _i, storedMethodNames_1, methodName, _a, _b, method;
return __generator(this, function (_c) {
Expand All @@ -112,7 +112,7 @@ var CallableBalancer = /** @class */ (function () {
if (!(_a < _b.length)) return [3 /*break*/, 8];
method = _b[_a];
if (!(method.name === methodName)) return [3 /*break*/, 7];
return [4 /*yield*/, __await(this.increaseMethodRank(method, this.INC_VALUE))];
return [4 /*yield*/, __await(this.increaseRank(method, this.INC_VALUE))];
case 4:
_c.sent();
return [4 /*yield*/, __await(method)];
Expand All @@ -134,7 +134,7 @@ var CallableBalancer = /** @class */ (function () {
/**
* Clear store
*/
CallableBalancer.prototype.resetStore = function () {
RedisFunctionsBalancer.prototype.resetStore = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
Expand All @@ -146,15 +146,15 @@ var CallableBalancer = /** @class */ (function () {
});
});
};
CallableBalancer.prototype.getStoreKey = function () {
RedisFunctionsBalancer.prototype.getStoreKey = function () {
return this._storeKey;
};
/**
* Return redis key to store list of methods with ranks
* @param methods
* @protected
*/
CallableBalancer.prototype.makeStoreKey = function (methods) {
RedisFunctionsBalancer.prototype.makeStoreKey = function (methods) {
var storeKeyArray = [this._STORE_PREFIX];
methods.forEach(function (method) {
storeKeyArray.push(method.name);
Expand All @@ -165,7 +165,7 @@ var CallableBalancer = /** @class */ (function () {
* Returns an Array stored in Redis in Rank order
* @private
*/
CallableBalancer.prototype.getRange = function () {
RedisFunctionsBalancer.prototype.getRange = function () {
return __awaiter(this, void 0, void 0, function () {
var storedMethodNames, args_1, result_1;
var _a;
Expand All @@ -190,6 +190,6 @@ var CallableBalancer = /** @class */ (function () {
});
});
};
return CallableBalancer;
return RedisFunctionsBalancer;
}());
exports.default = CallableBalancer;
exports.default = RedisFunctionsBalancer;
20 changes: 10 additions & 10 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ type RedisFunctions = {
zIncRbyAsync: (key: string, incValue: number, element: string) => Promise<string>;
};

export default class CallableBalancer {
export default class RedisFunctionsBalancer<T extends Function> {
private _storeKey: string;
private _methods: Array<Function>;
private _methods: Array<T>;
private readonly _STORE_PREFIX = 'balancer';
private readonly _redisClient: RedisClient;
private readonly INC_VALUE = 1;
Expand All @@ -22,7 +22,7 @@ export default class CallableBalancer {
* @param methods not empty array of functions
* @param redisClient
*/
constructor(methods: Array<Function>, redisClient: RedisClient) {
constructor(methods: Array<T>, redisClient: RedisClient) {
this._redisClient = redisClient;
this._methods = methods;
this._storeKey = this.makeStoreKey(methods);
Expand All @@ -36,23 +36,23 @@ export default class CallableBalancer {
};
}

public setMethods(methods: Array<Function>) {
public setMethods(methods: Array<T>) {
this._methods = methods;
this._storeKey = this.makeStoreKey(methods);
}

public async increaseMethodRank(method: Function, incValue: number = this.INC_VALUE) {
await this._functions.zIncRbyAsync(this._storeKey, incValue, method.name);
public async increaseRank(func: T, incValue: number = this.INC_VALUE) {
await this._functions.zIncRbyAsync(this._storeKey, incValue, func.name);
}

public async* getAsyncIterator(): AsyncIterableIterator<Function> {
public async* getAsyncIterator(): AsyncIterableIterator<T> {
let storedMethodNames = await this.getRange();

// Redis store defined
for (let methodName of storedMethodNames) {
for (let method of this._methods) {
if (method.name === methodName) {
await this.increaseMethodRank(method, this.INC_VALUE);
await this.increaseRank(method, this.INC_VALUE);
yield method;
}
}
Expand All @@ -75,9 +75,9 @@ export default class CallableBalancer {
* @param methods
* @protected
*/
protected makeStoreKey(methods: Array<Function>): string {
protected makeStoreKey(methods: Array<T>): string {
let storeKeyArray: Array<string> = [this._STORE_PREFIX];
methods.forEach((method: Function) => {
methods.forEach((method: T) => {
storeKeyArray.push(method.name);
});

Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
{
"name": "redis-functions-balancer",
"version": "1.0.5",
"version": "1.0.6",
"description": "Balance NodeJs functions with Redis",
"repository": "https://github.com/dmitryuk/RedisFunctionsBalancer",
"main": "index.ts",
"type": "module",
"main": "index.js",
"scripts": {
"test": "./node_modules/mocha/bin/mocha"
},
Expand Down
20 changes: 10 additions & 10 deletions test/iterator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import CallableBalancer from "../index";
import RedisFunctionsBalancer from "../index";
import {beforeEach} from "mocha";
import {promisify} from "util";
import assert = require("assert");
Expand All @@ -11,11 +11,11 @@ const B = () => new Promise(() => console.log('B'));
const C = () => new Promise(() => console.log('C'));

let methods = [A, B, C];
let balancer: CallableBalancer;
let zrangeAsync = promisify(redisClient.zrange).bind(redisClient);
let balancer: RedisFunctionsBalancer<Function>;
let zRangeAsync = promisify(redisClient.zrange).bind(redisClient);
describe('Test Callable Balancer', async function () {
beforeEach(async () => {
balancer = new CallableBalancer(methods, redisClient)
balancer = new RedisFunctionsBalancer(methods, redisClient)
await balancer.resetStore();
});

Expand All @@ -37,24 +37,24 @@ describe('Test Callable Balancer', async function () {

it('check redis state with iterator', async () => {
let key = balancer.getStoreKey();
let result = await zrangeAsync(key, 0, -1);
let result = await zRangeAsync(key, 0, -1);
assert.strictEqual(0, result.length);
let iterator = balancer.getAsyncIterator();
result = await zrangeAsync(key, 0, -1);
result = await zRangeAsync(key, 0, -1);
assert.strictEqual(0, result.length);

let data = await iterator.next();
result = await zrangeAsync(key, 0, -1);
result = await zRangeAsync(key, 0, -1);
assert.deepStrictEqual(['B', 'C', 'A'], result);
assert.strictEqual(A, data.value);

data = await iterator.next();
result = await zrangeAsync(key, 0, -1);
result = await zRangeAsync(key, 0, -1);
assert.deepStrictEqual(['C', 'A', 'B'], result);
assert.strictEqual(B, data.value);

data = await iterator.next();
result = await zrangeAsync(key, 0, -1);
result = await zRangeAsync(key, 0, -1);
assert.deepStrictEqual(['A', 'B', 'C'], result);
assert.strictEqual(C, data.value);
});
Expand All @@ -63,7 +63,7 @@ describe('Test Callable Balancer', async function () {
let iterator = await balancer.getAsyncIterator(),
data;
await iterator.next();
await balancer.increaseMethodRank(B, 2);
await balancer.increaseRank(B, 2);

iterator = await balancer.getAsyncIterator();
data = await iterator.next();
Expand Down

0 comments on commit 689ee8f

Please sign in to comment.