@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.afterCommit(() => func(instance));
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
- const { associations } = this.ormInstance.models[modelName];
64
- return [
65
- ...Object.keys(associations).map(association => {
66
- const sequelizeAssociation = associations[association];
67
- const associationOptions = {
68
- alias: sequelizeAssociation.as,
69
- name: sequelizeAssociation.target.name,
70
- accessKey: sequelizeAssociation.target.primaryKeyAttribute,
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
- return associationOptions;
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) => __awaiter(this, void 0, void 0, function* () {
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) => __awaiter(this, void 0, void 0, function* () {
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('Removing dependencies', { instance, instanceKey, dependencyKeys });
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('Invalidating dependent instances', { dependentInstancesKeys });
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('Removing dependencies', { dependentInstancesKeys, dependenciesToRemove });
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",
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",