@autofleet/matmon 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/lib/cache.d.ts +8 -0
- package/lib/cache.js +81 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.js +7 -0
- package/lib/locking.d.ts +3 -0
- package/lib/locking.js +26 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# matmon
|
|
2
|
+
|
|
3
|
+
# How to use:
|
|
4
|
+
|
|
5
|
+
import { getNewLRU, getWithCacheSupport } from '@autofleet/matmon';
|
|
6
|
+
const LIFETIME_IN_SEC = 15;
|
|
7
|
+
const SIZE = 300;
|
|
8
|
+
const VEHICLES_CACHE_KEY = 'vehicles';
|
|
9
|
+
|
|
10
|
+
const VehiclesCache = CacheUtil.getNewLRU(LIFETIME_IN_SEC, SIZE);
|
|
11
|
+
const getVehicle = async vehicleId => VehiclesCache.get(vehicleId);
|
|
12
|
+
const setVehicle = async (vehicleId, vehicle) => VehiclesCache.set(vehicleId, vehicle);
|
|
13
|
+
|
|
14
|
+
export const getVehicle = async (vehicleId, rideId, skipCache) => getWithCacheSupport({
|
|
15
|
+
cacheKey: VEHICLES_CACHE_KEY,
|
|
16
|
+
cacheGet: () => getVehicle(vehicleId),
|
|
17
|
+
cacheSet: value => setVehicle(vehicleId, value),
|
|
18
|
+
fetching: () => vehicleMs.getVehicle(vehicleId, rideId),
|
|
19
|
+
skipCache,
|
|
20
|
+
});
|
package/lib/cache.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const getNewLRU: (lifeTimeInSec: any, size: any) => any;
|
|
2
|
+
export declare const getWithCacheSupport: ({ cacheKey, cacheGet, cacheSet, fetching, skipCache, }: {
|
|
3
|
+
cacheKey: any;
|
|
4
|
+
cacheGet: any;
|
|
5
|
+
cacheSet: any;
|
|
6
|
+
fetching: any;
|
|
7
|
+
skipCache: any;
|
|
8
|
+
}) => Promise<any>;
|
package/lib/cache.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
|
+
};
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.getWithCacheSupport = exports.getNewLRU = void 0;
|
|
35
|
+
const lru_cache_1 = __importDefault(require("lru-cache"));
|
|
36
|
+
const locking = __importStar(require("./locking"));
|
|
37
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
38
|
+
dotenv_1.default.config();
|
|
39
|
+
const DEFAULT_CACHE_SIZE = 300;
|
|
40
|
+
const MAX_SIZE = 1000;
|
|
41
|
+
const MUTEX_MAP = {};
|
|
42
|
+
const getOptions = ({ lifeTimeInSec, size = DEFAULT_CACHE_SIZE, }) => ({
|
|
43
|
+
max: Math.min(size, MAX_SIZE),
|
|
44
|
+
maxAge: process.env.NODE_ENV !== 'test' ? 1000 * lifeTimeInSec : 0,
|
|
45
|
+
});
|
|
46
|
+
const getMutexByCacheKey = (key) => {
|
|
47
|
+
if (!MUTEX_MAP[key]) {
|
|
48
|
+
MUTEX_MAP[key] = locking.getMutex();
|
|
49
|
+
}
|
|
50
|
+
return MUTEX_MAP[key];
|
|
51
|
+
};
|
|
52
|
+
exports.getNewLRU = (lifeTimeInSec, size) => new lru_cache_1.default(getOptions({
|
|
53
|
+
lifeTimeInSec,
|
|
54
|
+
size,
|
|
55
|
+
}));
|
|
56
|
+
exports.getWithCacheSupport = ({ cacheKey, cacheGet, cacheSet, fetching, skipCache, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
57
|
+
if (skipCache || process.env.NODE_ENV === 'test') {
|
|
58
|
+
const res = yield fetching();
|
|
59
|
+
yield cacheSet(res);
|
|
60
|
+
return res;
|
|
61
|
+
}
|
|
62
|
+
let valueToReturn = null;
|
|
63
|
+
try {
|
|
64
|
+
yield locking.wrapWithMutex(getMutexByCacheKey(cacheKey), () => __awaiter(void 0, void 0, void 0, function* () {
|
|
65
|
+
valueToReturn = yield cacheGet();
|
|
66
|
+
if (!valueToReturn) {
|
|
67
|
+
valueToReturn = yield fetching();
|
|
68
|
+
yield cacheSet(valueToReturn);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// logger.info('get value from cache');
|
|
72
|
+
}
|
|
73
|
+
}));
|
|
74
|
+
// retry without locking if failed
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
valueToReturn = yield fetching();
|
|
78
|
+
yield cacheSet(valueToReturn);
|
|
79
|
+
}
|
|
80
|
+
return valueToReturn;
|
|
81
|
+
});
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
getNewLRU: (lifeTimeInSec: any, size: any) => any;
|
|
3
|
+
getWithCacheSupport: ({ cacheKey, cacheGet, cacheSet, fetching, skipCache, }: {
|
|
4
|
+
cacheKey: any;
|
|
5
|
+
cacheGet: any;
|
|
6
|
+
cacheSet: any;
|
|
7
|
+
fetching: any;
|
|
8
|
+
skipCache: any;
|
|
9
|
+
}) => Promise<any>;
|
|
10
|
+
};
|
|
11
|
+
export default _default;
|
package/lib/index.js
ADDED
package/lib/locking.d.ts
ADDED
package/lib/locking.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getMutex = exports.wrapWithMutex = void 0;
|
|
13
|
+
const async_mutex_1 = require("async-mutex");
|
|
14
|
+
const CACHE_LOCK_TIMEOUT_MILIS = 3000;
|
|
15
|
+
const LOCK_TIMEOUT_MESSAGE = 'mutex - locking timeout';
|
|
16
|
+
// eslint-disable-next-line import/prefer-default-export
|
|
17
|
+
exports.wrapWithMutex = (mutex, funcToRun) => __awaiter(void 0, void 0, void 0, function* () {
|
|
18
|
+
const release = yield mutex.acquire();
|
|
19
|
+
try {
|
|
20
|
+
yield funcToRun();
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
release();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
exports.getMutex = () => async_mutex_1.withTimeout(new async_mutex_1.Mutex(), CACHE_LOCK_TIMEOUT_MILIS, new Error(LOCK_TIMEOUT_MESSAGE));
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@autofleet/matmon",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "manage cache",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "rm -rf lib && tsc",
|
|
9
|
+
"prepublish": "npm run build",
|
|
10
|
+
"coverage": "jest --coverage --forceExit --runInBand",
|
|
11
|
+
"test": "jest --forceExit --runInBand",
|
|
12
|
+
"test-auto": "jest --watch --runInBand",
|
|
13
|
+
"linter": "./node_modules/.bin/eslint ."
|
|
14
|
+
},
|
|
15
|
+
"jest": {
|
|
16
|
+
"setupTestFrameworkScriptFile": "jest-extended",
|
|
17
|
+
"testURL": "http://localhost:8085/"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+ssh://git@gitlab.com/AutoFleet/matmon.git"
|
|
22
|
+
},
|
|
23
|
+
"author": "",
|
|
24
|
+
"license": "ISC",
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/Autofleet/matmon/issues"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/Autofleet/matmon",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@types/node": "^14.14.20",
|
|
31
|
+
"async-mutex": "^0.2.6",
|
|
32
|
+
"dotenv": "^8.2.0",
|
|
33
|
+
"lru-cache": "^6.0.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"typescript": "^3.9.5"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"lib/**/*"
|
|
40
|
+
]
|
|
41
|
+
}
|