@app-connect/core 1.7.29 → 1.7.30
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/lib/cacheCleanup.js +42 -3
- package/package.json +1 -1
- package/releaseNotes.json +12 -0
- package/test/lib/cacheCleanup.test.js +86 -1
package/lib/cacheCleanup.js
CHANGED
|
@@ -1,21 +1,60 @@
|
|
|
1
1
|
const { Op } = require('sequelize');
|
|
2
2
|
const { CacheModel } = require('../models/cacheModel');
|
|
3
|
+
const { AccountDataModel } = require('../models/accountDataModel');
|
|
3
4
|
const logger = require('./logger');
|
|
4
5
|
|
|
6
|
+
const ACCOUNT_CONTACT_DATA_KEY_PATTERN = 'contact-%';
|
|
7
|
+
const ACCOUNT_CONTACT_DATA_RETENTION_MONTHS = 3;
|
|
8
|
+
|
|
5
9
|
async function clearExpiredCache({ now = new Date() } = {}) {
|
|
6
|
-
const
|
|
10
|
+
const cacheDeletedCount = await clearExpiredCacheRows({ now });
|
|
11
|
+
const accountContactDataDeletedCount = await clearExpiredAccountContactData({ now });
|
|
12
|
+
const deletedCount = cacheDeletedCount + accountContactDataDeletedCount;
|
|
13
|
+
|
|
14
|
+
logger.info('Expired cache cleanup completed', {
|
|
15
|
+
deletedCount,
|
|
16
|
+
cacheDeletedCount,
|
|
17
|
+
accountContactDataDeletedCount
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return deletedCount;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getAccountContactDataCutoffDate({ now, retentionMonths }) {
|
|
24
|
+
const cutoffDate = new Date(now.getTime());
|
|
25
|
+
cutoffDate.setMonth(cutoffDate.getMonth() - retentionMonths);
|
|
26
|
+
return cutoffDate;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function clearExpiredCacheRows({ now }) {
|
|
30
|
+
return CacheModel.destroy({
|
|
7
31
|
where: {
|
|
8
32
|
expiry: {
|
|
9
33
|
[Op.lte]: now
|
|
10
34
|
}
|
|
11
35
|
}
|
|
12
36
|
});
|
|
37
|
+
}
|
|
13
38
|
|
|
14
|
-
|
|
39
|
+
async function clearExpiredAccountContactData({
|
|
40
|
+
now = new Date(),
|
|
41
|
+
retentionMonths = ACCOUNT_CONTACT_DATA_RETENTION_MONTHS
|
|
42
|
+
} = {}) {
|
|
43
|
+
const cutoffDate = getAccountContactDataCutoffDate({ now, retentionMonths });
|
|
15
44
|
|
|
16
|
-
return
|
|
45
|
+
return AccountDataModel.destroy({
|
|
46
|
+
where: {
|
|
47
|
+
dataKey: {
|
|
48
|
+
[Op.like]: ACCOUNT_CONTACT_DATA_KEY_PATTERN
|
|
49
|
+
},
|
|
50
|
+
createdAt: {
|
|
51
|
+
[Op.lt]: cutoffDate
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
17
55
|
}
|
|
18
56
|
|
|
19
57
|
module.exports = {
|
|
58
|
+
clearExpiredAccountContactData,
|
|
20
59
|
clearExpiredCache
|
|
21
60
|
};
|
package/package.json
CHANGED
package/releaseNotes.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const { CacheModel } = require('../../models/cacheModel');
|
|
2
|
-
const {
|
|
2
|
+
const { AccountDataModel } = require('../../models/accountDataModel');
|
|
3
|
+
const { clearExpiredAccountContactData, clearExpiredCache } = require('../../lib/cacheCleanup');
|
|
3
4
|
|
|
4
5
|
describe('cacheCleanup', () => {
|
|
5
6
|
beforeEach(async () => {
|
|
6
7
|
await CacheModel.destroy({ where: {} });
|
|
8
|
+
await AccountDataModel.destroy({ where: {} });
|
|
7
9
|
});
|
|
8
10
|
|
|
9
11
|
test('deletes only cache records whose expiry has passed', async () => {
|
|
@@ -39,4 +41,87 @@ describe('cacheCleanup', () => {
|
|
|
39
41
|
expect(await CacheModel.findByPk('active-cache')).not.toBeNull();
|
|
40
42
|
expect(await CacheModel.findByPk('cache-without-expiry')).not.toBeNull();
|
|
41
43
|
});
|
|
44
|
+
|
|
45
|
+
test('deletes only account contact data older than three months', async () => {
|
|
46
|
+
const now = new Date('2026-06-08T00:00:00.000Z');
|
|
47
|
+
|
|
48
|
+
await AccountDataModel.bulkCreate([
|
|
49
|
+
{
|
|
50
|
+
rcAccountId: 'account-1',
|
|
51
|
+
platformName: 'test-platform',
|
|
52
|
+
dataKey: 'contact-+1111111111',
|
|
53
|
+
data: [{ id: 'old-contact' }],
|
|
54
|
+
createdAt: new Date('2026-03-07T23:59:59.000Z'),
|
|
55
|
+
updatedAt: new Date('2026-03-07T23:59:59.000Z')
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
rcAccountId: 'account-1',
|
|
59
|
+
platformName: 'test-platform',
|
|
60
|
+
dataKey: 'contact-+2222222222',
|
|
61
|
+
data: [{ id: 'exact-cutoff-contact' }],
|
|
62
|
+
createdAt: new Date('2026-03-08T00:00:00.000Z'),
|
|
63
|
+
updatedAt: new Date('2026-03-08T00:00:00.000Z')
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
rcAccountId: 'account-1',
|
|
67
|
+
platformName: 'test-platform',
|
|
68
|
+
dataKey: 'contact-+3333333333',
|
|
69
|
+
data: [{ id: 'active-contact' }],
|
|
70
|
+
createdAt: new Date('2026-03-08T00:00:01.000Z'),
|
|
71
|
+
updatedAt: new Date('2026-03-08T00:00:01.000Z')
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
rcAccountId: 'account-1',
|
|
75
|
+
platformName: 'test-platform',
|
|
76
|
+
dataKey: 'pluginData',
|
|
77
|
+
data: { jwtToken: 'plugin-token' },
|
|
78
|
+
createdAt: new Date('2026-03-07T23:59:59.000Z'),
|
|
79
|
+
updatedAt: new Date('2026-03-07T23:59:59.000Z')
|
|
80
|
+
}
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
const deletedCount = await clearExpiredAccountContactData({ now });
|
|
84
|
+
|
|
85
|
+
expect(deletedCount).toBe(1);
|
|
86
|
+
expect(await AccountDataModel.findOne({
|
|
87
|
+
where: { rcAccountId: 'account-1', platformName: 'test-platform', dataKey: 'contact-+1111111111' }
|
|
88
|
+
})).toBeNull();
|
|
89
|
+
expect(await AccountDataModel.findOne({
|
|
90
|
+
where: { rcAccountId: 'account-1', platformName: 'test-platform', dataKey: 'contact-+2222222222' }
|
|
91
|
+
})).not.toBeNull();
|
|
92
|
+
expect(await AccountDataModel.findOne({
|
|
93
|
+
where: { rcAccountId: 'account-1', platformName: 'test-platform', dataKey: 'contact-+3333333333' }
|
|
94
|
+
})).not.toBeNull();
|
|
95
|
+
expect(await AccountDataModel.findOne({
|
|
96
|
+
where: { rcAccountId: 'account-1', platformName: 'test-platform', dataKey: 'pluginData' }
|
|
97
|
+
})).not.toBeNull();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('clearExpiredCache includes expired account contact data cleanup', async () => {
|
|
101
|
+
const now = new Date('2026-06-08T00:00:00.000Z');
|
|
102
|
+
|
|
103
|
+
await CacheModel.create({
|
|
104
|
+
id: 'expired-cache',
|
|
105
|
+
userId: 'user-1',
|
|
106
|
+
cacheKey: 'auth-session',
|
|
107
|
+
status: 'expired',
|
|
108
|
+
expiry: new Date('2026-06-07T23:59:59.000Z')
|
|
109
|
+
});
|
|
110
|
+
await AccountDataModel.create({
|
|
111
|
+
rcAccountId: 'account-1',
|
|
112
|
+
platformName: 'test-platform',
|
|
113
|
+
dataKey: 'contact-+1111111111',
|
|
114
|
+
data: [{ id: 'old-contact' }],
|
|
115
|
+
createdAt: new Date('2026-03-07T23:59:59.000Z'),
|
|
116
|
+
updatedAt: new Date('2026-03-07T23:59:59.000Z')
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const deletedCount = await clearExpiredCache({ now });
|
|
120
|
+
|
|
121
|
+
expect(deletedCount).toBe(2);
|
|
122
|
+
expect(await CacheModel.findByPk('expired-cache')).toBeNull();
|
|
123
|
+
expect(await AccountDataModel.findOne({
|
|
124
|
+
where: { rcAccountId: 'account-1', platformName: 'test-platform', dataKey: 'contact-+1111111111' }
|
|
125
|
+
})).toBeNull();
|
|
126
|
+
});
|
|
42
127
|
});
|