@autofleet/matmon 2.0.3 → 2.0.4-beta-2
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.
|
@@ -12,6 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const newrelic_1 = __importDefault(require("newrelic"));
|
|
15
16
|
const logger_1 = __importDefault(require("../logger"));
|
|
16
17
|
const util_1 = require("util");
|
|
17
18
|
const { AF_SERVICE_NAME } = process.env;
|
|
@@ -20,7 +21,7 @@ const INVALIDATION_HOOKS = ['afterSave', 'afterUpdate', 'afterDestroy'];
|
|
|
20
21
|
const BULK_HOOKS = ['beforeBulkUpdate', 'beforeBulkDestroy'];
|
|
21
22
|
const generateInstanceKey = (name, id) => `${AF_SERVICE_NAME}:${ORM_CACHE_PREFIX}:${name}_${id}`;
|
|
22
23
|
const generateDependencyKey = (modelName, associationName, associationId) => `${AF_SERVICE_NAME}:${ORM_CACHE_PREFIX}:${modelName}_${associationName}_${associationId}_DEPENDENCIES`;
|
|
23
|
-
const getInstanceDependencyKeys = (modelOptions, instance) => {
|
|
24
|
+
const getInstanceDependencyKeys = (modelOptions, instance) => newrelic_1.default.startSegment(`${ORM_CACHE_PREFIX}:getInstanceDependencyKeys`, true, () => {
|
|
24
25
|
const keys = modelOptions.associations
|
|
25
26
|
.filter((associationOptions) => instance[associationOptions.alias])
|
|
26
27
|
.map((associationOptions) => {
|
|
@@ -41,11 +42,17 @@ const getInstanceDependencyKeys = (modelOptions, instance) => {
|
|
|
41
42
|
];
|
|
42
43
|
});
|
|
43
44
|
return keys.reduce((flattenArray, array) => flattenArray.concat(array), []);
|
|
44
|
-
};
|
|
45
|
+
});
|
|
45
46
|
const handleTransactionHook = (instance, options, func) => {
|
|
46
47
|
const { transaction } = options;
|
|
47
48
|
if (transaction) {
|
|
48
|
-
transaction
|
|
49
|
+
if (!transaction[ORM_CACHE_PREFIX]) {
|
|
50
|
+
transaction[ORM_CACHE_PREFIX] = new Set();
|
|
51
|
+
}
|
|
52
|
+
if (!transaction[ORM_CACHE_PREFIX].has(instance.id)) {
|
|
53
|
+
transaction.afterCommit(() => func(instance));
|
|
54
|
+
transaction[ORM_CACHE_PREFIX].add(instance.id);
|
|
55
|
+
}
|
|
49
56
|
}
|
|
50
57
|
else {
|
|
51
58
|
func(instance);
|
|
@@ -60,26 +67,28 @@ class SequelizeAdapter {
|
|
|
60
67
|
return this.ormInstance.models[modelName];
|
|
61
68
|
}
|
|
62
69
|
getModelDependencies(modelName) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (sequelizeAssociation.through) {
|
|
73
|
-
const relationModel = sequelizeAssociation.through.model;
|
|
74
|
-
associationOptions.innerAssociation = {
|
|
75
|
-
alias: relationModel.name,
|
|
76
|
-
name: relationModel.name,
|
|
77
|
-
accessKey: relationModel.primaryKeyAttribute,
|
|
70
|
+
return newrelic_1.default.startSegment(`${ORM_CACHE_PREFIX}:getModelDependencies`, true, () => {
|
|
71
|
+
const { associations } = this.ormInstance.models[modelName];
|
|
72
|
+
return [
|
|
73
|
+
...Object.keys(associations).map(association => {
|
|
74
|
+
const sequelizeAssociation = associations[association];
|
|
75
|
+
const associationOptions = {
|
|
76
|
+
alias: sequelizeAssociation.as,
|
|
77
|
+
name: sequelizeAssociation.target.name,
|
|
78
|
+
accessKey: sequelizeAssociation.target.primaryKeyAttribute,
|
|
78
79
|
};
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
if (sequelizeAssociation.through) {
|
|
81
|
+
const relationModel = sequelizeAssociation.through.model;
|
|
82
|
+
associationOptions.innerAssociation = {
|
|
83
|
+
alias: relationModel.name,
|
|
84
|
+
name: relationModel.name,
|
|
85
|
+
accessKey: relationModel.primaryKeyAttribute,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return associationOptions;
|
|
89
|
+
}),
|
|
90
|
+
];
|
|
91
|
+
});
|
|
83
92
|
}
|
|
84
93
|
debug(message, payload) {
|
|
85
94
|
if (this.debugMode) {
|
|
@@ -87,7 +96,7 @@ class SequelizeAdapter {
|
|
|
87
96
|
}
|
|
88
97
|
}
|
|
89
98
|
injectGetWithCacheFunction(cache, modelOptions) {
|
|
90
|
-
const addDependencies = (instance) =>
|
|
99
|
+
const addDependencies = (instance) => newrelic_1.default.startSegment(`${ORM_CACHE_PREFIX}:addDependencies`, true, () => {
|
|
91
100
|
const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);
|
|
92
101
|
const instanceKey = generateInstanceKey(modelOptions.name, instance.id);
|
|
93
102
|
this.debug('Adding dependencies', { instanceKey, dependencyKeys });
|
|
@@ -117,19 +126,19 @@ class SequelizeAdapter {
|
|
|
117
126
|
});
|
|
118
127
|
}
|
|
119
128
|
addInvalidationHooks(cache, modelOptions) {
|
|
120
|
-
const invalidateModelInstance = (instance) =>
|
|
129
|
+
const invalidateModelInstance = (hook, instance) => newrelic_1.default.startSegment(`${ORM_CACHE_PREFIX}:invalidateModelInstance`, true, () => {
|
|
121
130
|
const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);
|
|
122
131
|
const instanceKey = generateInstanceKey(modelOptions.name, instance.id);
|
|
123
|
-
this.debug(
|
|
132
|
+
this.debug(`Removing dependencies (triggered by ${hook})`, { instance, instanceKey, dependencyKeys });
|
|
124
133
|
const removeMulti = cache.getClient().multi();
|
|
125
134
|
const removeMultiAsync = util_1.promisify(removeMulti.exec).bind(removeMulti);
|
|
126
135
|
dependencyKeys.map(key => removeMulti.srem(key, instanceKey));
|
|
127
136
|
removeMulti.del(instanceKey);
|
|
128
137
|
return removeMultiAsync();
|
|
129
138
|
});
|
|
130
|
-
const invalidateModelInstanceByAssociation = (association, associationId) => __awaiter(this, void 0, void 0, function* () {
|
|
139
|
+
const invalidateModelInstanceByAssociation = (hook, association, associationId) => newrelic_1.default.startSegment(`${ORM_CACHE_PREFIX}:invalidateModelInstanceByAssociation`, true, () => __awaiter(this, void 0, void 0, function* () {
|
|
131
140
|
const dependentInstancesKeys = yield cache.getClient().smembersAsync(generateDependencyKey(modelOptions.name, association, associationId));
|
|
132
|
-
this.debug(
|
|
141
|
+
this.debug(`Invalidating dependent instances (triggered by ${hook})`, { dependentInstancesKeys });
|
|
133
142
|
const removeMulti = cache.getClient().multi();
|
|
134
143
|
const removeMultiAsync = util_1.promisify(removeMulti.exec).bind(removeMulti);
|
|
135
144
|
const dependenciesToRemove = yield Promise.all(dependentInstancesKeys.map((instanceKey) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -142,22 +151,20 @@ class SequelizeAdapter {
|
|
|
142
151
|
removeMulti.del(instanceKey);
|
|
143
152
|
return dependencyKeys;
|
|
144
153
|
})));
|
|
145
|
-
this.debug(
|
|
154
|
+
this.debug(`Removing dependencies (triggered by ${hook})`, { dependentInstancesKeys, dependenciesToRemove });
|
|
146
155
|
return removeMultiAsync();
|
|
147
|
-
});
|
|
156
|
+
}));
|
|
148
157
|
const model = this.getModel(modelOptions.name);
|
|
149
|
-
INVALIDATION_HOOKS.map(hook => model.addHook(hook, (instance, options) => handleTransactionHook(instance, options, instance => invalidateModelInstance(instance))));
|
|
158
|
+
INVALIDATION_HOOKS.map(hook => model.addHook(hook, (instance, options) => handleTransactionHook(instance, options, instance => invalidateModelInstance(hook, instance))));
|
|
150
159
|
BULK_HOOKS.map(hook => model.addHook(hook, options => options.individualHook = true));
|
|
151
160
|
modelOptions.associations = this.getModelDependencies(modelOptions.name);
|
|
152
161
|
this.debug(`Adding Invalidations Hooks to ${modelOptions.name}'s associations`, { associations: modelOptions.associations });
|
|
153
162
|
modelOptions.associations.map((associationOptions) => {
|
|
154
163
|
const associationModel = this.getModel(associationOptions.name);
|
|
155
|
-
INVALIDATION_HOOKS.map(hook => associationModel.addHook(hook, (instance, options) => handleTransactionHook(instance, options, associationInstance => invalidateModelInstanceByAssociation(associationOptions.name, associationInstance[associationOptions.accessKey]))));
|
|
156
|
-
BULK_HOOKS.map(hook => associationModel.addHook(hook, options => options.individualHook = true));
|
|
164
|
+
INVALIDATION_HOOKS.map(hook => associationModel.addHook(hook, (instance, options) => handleTransactionHook(instance, options, associationInstance => invalidateModelInstanceByAssociation(hook, associationOptions.name, associationInstance[associationOptions.accessKey]))));
|
|
157
165
|
if (associationOptions.innerAssociation) {
|
|
158
166
|
const innerAssociationModel = this.getModel(associationOptions.innerAssociation.name);
|
|
159
|
-
INVALIDATION_HOOKS.map(hook => innerAssociationModel.addHook(hook, (instance, options) => handleTransactionHook(instance, options, innerAssociationInstance => invalidateModelInstanceByAssociation(associationOptions.innerAssociation.name, innerAssociationInstance[associationOptions.innerAssociation.accessKey]))));
|
|
160
|
-
BULK_HOOKS.map(hook => innerAssociationModel.addHook(hook, options => options.individualHook = true));
|
|
167
|
+
INVALIDATION_HOOKS.map(hook => innerAssociationModel.addHook(hook, (instance, options) => handleTransactionHook(instance, options, innerAssociationInstance => invalidateModelInstanceByAssociation(hook, associationOptions.innerAssociation.name, innerAssociationInstance[associationOptions.innerAssociation.accessKey]))));
|
|
161
168
|
}
|
|
162
169
|
});
|
|
163
170
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/matmon",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4-beta-2",
|
|
4
4
|
"description": "manage cache",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"bluebird": "^3.7.2",
|
|
33
33
|
"dotenv": "^8.2.0",
|
|
34
34
|
"lru-cache": "^6.0.0",
|
|
35
|
+
"newrelic": "^7.5.2",
|
|
35
36
|
"redis": "^3.0.2",
|
|
36
37
|
"redis-lock": "^0.1.4",
|
|
37
38
|
"sequelize": "^6.6.2",
|