3 files changed
+37
-14
No files matched your search
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "client",
|
"name": "client",
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "client",
|
"name": "client",
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.13.3",
|
"@emotion/react": "^11.13.3",
|
||||||
"@emotion/styled": "^11.13.0",
|
"@emotion/styled": "^11.13.0",
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "client",
|
"name": "client",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const CHECKS_COLLECTION = "checks";
|
|||||||
const BACKUP_COLLECTION = "checks_backup";
|
const BACKUP_COLLECTION = "checks_backup";
|
||||||
const FAILED_DOCS_COLLECTION = "checks_migration_failed";
|
const FAILED_DOCS_COLLECTION = "checks_migration_failed";
|
||||||
const BATCH_SIZE = 1000;
|
const BATCH_SIZE = 1000;
|
||||||
|
const NAMESPACE_EXISTS_CODE = 48;
|
||||||
|
|
||||||
interface MigrationStats {
|
interface MigrationStats {
|
||||||
totalSource: number;
|
totalSource: number;
|
||||||
@@ -41,6 +42,13 @@ const backupAndDropExistingCollection = async () => {
|
|||||||
if (collections.length === 0) {
|
if (collections.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The Check model declares `timeseries`, so on a fresh database Mongoose's autoCreate
|
||||||
|
// already creates `checks` as a time-series collection. Skip and return false
|
||||||
|
if (collections[0]?.type === "timeseries") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const backupExists = await db.listCollections({ name: BACKUP_COLLECTION }).toArray();
|
const backupExists = await db.listCollections({ name: BACKUP_COLLECTION }).toArray();
|
||||||
if (backupExists.length > 0) {
|
if (backupExists.length > 0) {
|
||||||
throw new Error(`Backup collection "${BACKUP_COLLECTION}" already exists. ` + `Please remove it manually before running migration.`);
|
throw new Error(`Backup collection "${BACKUP_COLLECTION}" already exists. ` + `Please remove it manually before running migration.`);
|
||||||
@@ -59,13 +67,21 @@ const createTimeSeriesCollection = async (backedUp: boolean) => {
|
|||||||
try {
|
try {
|
||||||
const existing = await db.listCollections({ name: CHECKS_COLLECTION }).toArray();
|
const existing = await db.listCollections({ name: CHECKS_COLLECTION }).toArray();
|
||||||
if (existing.length === 0) {
|
if (existing.length === 0) {
|
||||||
await db.createCollection(CHECKS_COLLECTION, {
|
try {
|
||||||
timeseries: {
|
await db.createCollection(CHECKS_COLLECTION, {
|
||||||
timeField: "createdAt",
|
timeseries: {
|
||||||
metaField: "metadata",
|
timeField: "createdAt",
|
||||||
granularity: "seconds",
|
metaField: "metadata",
|
||||||
},
|
granularity: "seconds",
|
||||||
});
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// Mongoose's autoCreate can create `checks` concurrently with this migration,
|
||||||
|
// already exists as a time-series collection, this is success, otherwise throw
|
||||||
|
if ((error as { code?: number })?.code !== NAMESPACE_EXISTS_CODE) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await db
|
await db
|
||||||
@@ -80,7 +96,11 @@ const createTimeSeriesCollection = async (backedUp: boolean) => {
|
|||||||
]);
|
]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (backedUp) {
|
if (backedUp) {
|
||||||
await restoreFromBackup();
|
try {
|
||||||
|
await restoreFromBackup();
|
||||||
|
} catch (restoreError) {
|
||||||
|
console.error("rollback failed:", restoreError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@@ -123,8 +143,7 @@ const migrateBackupData = async (backedUp: boolean): Promise<MigrationStats> =>
|
|||||||
const target = db.collection(CHECKS_COLLECTION);
|
const target = db.collection(CHECKS_COLLECTION);
|
||||||
|
|
||||||
stats.totalSource = await source.countDocuments();
|
stats.totalSource = await source.countDocuments();
|
||||||
|
const cursor = source.find();
|
||||||
const cursor = source.find().addCursorFlag("noCursorTimeout", true);
|
|
||||||
const operations: AnyBulkWriteOperation<Document>[] = [];
|
const operations: AnyBulkWriteOperation<Document>[] = [];
|
||||||
const invalidDocs: Document[] = [];
|
const invalidDocs: Document[] = [];
|
||||||
|
|
||||||
@@ -166,7 +185,11 @@ const migrateBackupData = async (backedUp: boolean): Promise<MigrationStats> =>
|
|||||||
return stats;
|
return stats;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (backedUp) {
|
if (backedUp) {
|
||||||
await restoreFromBackup();
|
try {
|
||||||
|
await restoreFromBackup();
|
||||||
|
} catch (restoreError) {
|
||||||
|
console.error("rollback failed:", restoreError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user