Skip to content

Commit 347864c

Browse files
committed
feat: add release field to string & indexing migrations
1 parent 1de0465 commit 347864c

4 files changed

Lines changed: 137 additions & 5 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* @file Add index on `payload.release` for all per-project events collections
3+
* Collections pattern: `events:{projectId}` in the events database
4+
*/
5+
module.exports = {
6+
async up(db) {
7+
const indexSpec = { 'payload.release': 1 };
8+
const indexOptions = {
9+
name: 'payloadRelease',
10+
background: true,
11+
sparse: true,
12+
};
13+
14+
const collections = await db.listCollections().toArray();
15+
const targetCollections = collections
16+
.map(c => c.name)
17+
.filter(name => name && name.startsWith('events:'));
18+
19+
console.log(`Found ${targetCollections.length} events collections`);
20+
21+
for (const name of targetCollections) {
22+
const coll = db.collection(name);
23+
const existing = await coll.indexes();
24+
25+
const alreadyExists = existing.some(idx => idx.name === indexOptions.name) ||
26+
existing.some(idx => idx.key && idx.key['payload.release'] === 1);
27+
28+
if (alreadyExists) {
29+
console.log(`Index already exists on ${name}. Skipped.`);
30+
continue;
31+
}
32+
33+
console.log(`Creating index ${indexOptions.name} on ${name}...`);
34+
await coll.createIndex(indexSpec, indexOptions);
35+
}
36+
},
37+
38+
async down(db) {
39+
const indexName = 'idx_payload_release';
40+
41+
const collections = await db.listCollections().toArray();
42+
const targetCollections = collections
43+
.map(c => c.name)
44+
.filter(name => name && name.startsWith('events:'));
45+
46+
console.log(`Found ${targetCollections.length} events collections`);
47+
48+
for (const name of targetCollections) {
49+
const coll = db.collection(name);
50+
51+
try {
52+
console.log(`Dropping index ${indexName} on ${name}...`);
53+
await coll.dropIndex(indexName);
54+
} catch (e) {
55+
// If index does not exist, ignore
56+
if (e && e.codeName !== 'IndexNotFound') {
57+
throw e;
58+
}
59+
}
60+
}
61+
},
62+
};
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* Convert all payload.release fields to strings across all per-project events collections.
3+
* Collections pattern: events:{projectId}
4+
*/
5+
module.exports = {
6+
async up(db) {
7+
const collections = await db.listCollections().toArray();
8+
const targetCollections = collections
9+
.map(c => c.name)
10+
.filter(name => name && name.startsWith('events:'));
11+
12+
console.log(`Found ${targetCollections.length} events collections to process`);
13+
14+
for (const name of targetCollections) {
15+
const coll = db.collection(name);
16+
17+
// Find docs where payload.release exists
18+
const cursor = coll.find(
19+
{ 'payload.release': { $exists: true } },
20+
{
21+
projection: {
22+
_id: 1,
23+
'payload.release': 1,
24+
},
25+
}
26+
);
27+
28+
let converted = 0;
29+
let scanned = 0;
30+
const ops = [];
31+
const BATCH_SIZE = 1000;
32+
33+
while (await cursor.hasNext()) {
34+
const doc = await cursor.next();
35+
36+
scanned++;
37+
const releaseValue = doc && doc.payload ? doc.payload.release : undefined;
38+
39+
if (typeof releaseValue !== 'string') {
40+
ops.push({
41+
updateOne: {
42+
filter: { _id: doc._id },
43+
update: { $set: { 'payload.release': String(releaseValue) } },
44+
},
45+
});
46+
converted++;
47+
}
48+
49+
if (ops.length >= BATCH_SIZE) {
50+
await coll.bulkWrite(ops, { ordered: false });
51+
ops.length = 0;
52+
}
53+
}
54+
55+
if (ops.length > 0) {
56+
await coll.bulkWrite(ops, { ordered: false });
57+
}
58+
59+
console.log(`[${name}] scanned=${scanned}, converted=${converted}`);
60+
}
61+
},
62+
63+
async down() {
64+
console.log('Down migration is not implemented: cannot reliably restore original non-string types for payload.release.');
65+
},
66+
};

workers/grouper/src/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ export default class GrouperWorker extends Worker {
101101
public async handle(task: GroupWorkerTask<ErrorsCatcherType>): Promise<void> {
102102
let uniqueEventHash = await this.getUniqueEventHash(task);
103103

104+
// FIX RELEASE TYPE
105+
// TODO: REMOVE AFTER 01.01.2026, after the most of the users update to new js catcher
106+
if (task.payload && task.payload.release !== undefined) {
107+
task.payload = {
108+
...task.payload,
109+
release: String(task.payload.release)
110+
}
111+
}
112+
104113
/**
105114
* Find event by group hash.
106115
*/

yarn.lock

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4629,11 +4629,6 @@ jest@^29.2.2:
46294629
import-local "^3.0.2"
46304630
jest-cli "^29.7.0"
46314631

4632-
js-levenshtein@^1.1.6:
4633-
version "1.1.6"
4634-
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
4635-
integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
4636-
46374632
js-tokens@^4.0.0:
46384633
version "4.0.0"
46394634
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"

0 commit comments

Comments
 (0)