From e6bc3c9a75c6b435f7794d606e0088e2359c8f61 Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 14 Oct 2019 00:00:00 +0000 Subject: [PATCH] Add tool to delete old families --- package.json | 3 + src/cli/count-families.ts | 27 ++++ src/cli/delete-old-families.ts | 28 ++++ src/cli/find-old-families.ts | 28 ++++ src/function/cleanup/delete-families.ts | 149 ++++++++++++++++++++ src/function/cleanup/delete-old-families.ts | 69 +++++++++ 6 files changed, 304 insertions(+) create mode 100644 src/cli/count-families.ts create mode 100644 src/cli/delete-old-families.ts create mode 100644 src/cli/find-old-families.ts create mode 100644 src/function/cleanup/delete-families.ts create mode 100644 src/function/cleanup/delete-old-families.ts diff --git a/package.json b/package.json index a14ced8..b68330a 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,9 @@ "build": "npm run build:json && npm run build:ts && npm run lint", "build:json": "node ./scripts/build-schemas.js", "build:ts": "tsc", + "tool:find-old-families": "node build/cli/find-old-families.js", + "tool:delete-old-families": "node build/cli/delete-old-families.js", + "tool:count-families": "node build/cli/count-families.js", "watch": "nodemon ./build/index.js" }, "repository": { diff --git a/src/cli/count-families.ts b/src/cli/count-families.ts new file mode 100644 index 0000000..d55716b --- /dev/null +++ b/src/cli/count-families.ts @@ -0,0 +1,27 @@ +/* + * server component for the TimeLimit App + * Copyright (C) 2019 Jonas Lochmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { defaultDatabase } from '../database' + +const database = defaultDatabase + +database.family.count() + .then((res) => console.log(JSON.stringify(res))) + .catch((ex) => { + console.warn(ex) + process.exit(1) + }) diff --git a/src/cli/delete-old-families.ts b/src/cli/delete-old-families.ts new file mode 100644 index 0000000..227339d --- /dev/null +++ b/src/cli/delete-old-families.ts @@ -0,0 +1,28 @@ +/* + * server component for the TimeLimit App + * Copyright (C) 2019 Jonas Lochmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { defaultDatabase } from '../database' +import { deleteOldFamilies } from '../function/cleanup/delete-old-families' + +const database = defaultDatabase + +deleteOldFamilies(database) + .then(() => console.log('done')) + .catch((ex) => { + console.warn(ex) + process.exit(1) + }) diff --git a/src/cli/find-old-families.ts b/src/cli/find-old-families.ts new file mode 100644 index 0000000..f21e12a --- /dev/null +++ b/src/cli/find-old-families.ts @@ -0,0 +1,28 @@ +/* + * server component for the TimeLimit App + * Copyright (C) 2019 Jonas Lochmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { defaultDatabase } from '../database' +import { findOldFamilyIds } from '../function/cleanup/delete-old-families' + +const database = defaultDatabase + +findOldFamilyIds(database) + .then((res) => console.log(JSON.stringify(res))) + .catch((ex) => { + console.warn(ex) + process.exit(1) + }) diff --git a/src/function/cleanup/delete-families.ts b/src/function/cleanup/delete-families.ts new file mode 100644 index 0000000..028c167 --- /dev/null +++ b/src/function/cleanup/delete-families.ts @@ -0,0 +1,149 @@ +/* + * server component for the TimeLimit App + * Copyright (C) 2019 Jonas Lochmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import * as Sequelize from 'sequelize' +import { Database } from '../../database' + +export async function deleteFamilies ({ database, familiyIds }: { + database: Database + familiyIds: Array +}) { + if (familiyIds.length === 0) { + return + } + + await database.transaction(async (transaction) => { + // app + await database.app.destroy({ + where: { + familyId: { + [Sequelize.Op.in]: familiyIds + } + }, + transaction + }) + + // app activity + await database.appActivity.destroy({ + where: { + familyId: { + [Sequelize.Op.in]: familiyIds + } + }, + transaction + }) + + // category + await database.category.destroy({ + where: { + familyId: { + [Sequelize.Op.in]: familiyIds + } + }, + transaction + }) + + // categoryapp + await database.categoryApp.destroy({ + where: { + familyId: { + [Sequelize.Op.in]: familiyIds + } + }, + transaction + }) + + // purchase + await database.purchase.destroy({ + where: { + familyId: { + [Sequelize.Op.in]: familiyIds + } + }, + transaction + }) + + // timelimitrule + await database.timelimitRule.destroy({ + where: { + familyId: { + [Sequelize.Op.in]: familiyIds + } + }, + transaction + }) + + // usedtime + await database.usedTime.destroy({ + where: { + familyId: { + [Sequelize.Op.in]: familiyIds + } + }, + transaction + }) + + // user + await database.user.destroy({ + where: { + familyId: { + [Sequelize.Op.in]: familiyIds + } + }, + transaction + }) + + // device + const oldDeviceAuthTokens = await database.device.findAll({ + where: { + familyId: { + [Sequelize.Op.in]: familiyIds + } + }, + attributes: ['deviceAuthToken'], + transaction + }).map((item) => item.deviceAuthToken) + + await database.device.destroy({ + where: { + familyId: { + [Sequelize.Op.in]: familiyIds + } + }, + transaction + }) + + // olddevice + if (oldDeviceAuthTokens.length > 0) { + await database.oldDevice.bulkCreate( + oldDeviceAuthTokens.map((item) => ({ + deviceAuthToken: item + })) + ) + } + + // family + await database.family.destroy({ + where: { + familyId: { + [Sequelize.Op.in]: familiyIds + } + }, + transaction + }) + }) +} diff --git a/src/function/cleanup/delete-old-families.ts b/src/function/cleanup/delete-old-families.ts new file mode 100644 index 0000000..b3753e7 --- /dev/null +++ b/src/function/cleanup/delete-old-families.ts @@ -0,0 +1,69 @@ +/* + * server component for the TimeLimit App + * Copyright (C) 2019 Jonas Lochmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { difference } from 'lodash' +import * as Sequelize from 'sequelize' +import { Database } from '../../database' +import { deleteFamilies } from './delete-families' + +export async function deleteOldFamilies (database: Database) { + console.log('deleteOldFamilies()') + + const oldFamilyIds = await findOldFamilyIds(database) + + console.log('oldFamilyIds: ' + JSON.stringify(oldFamilyIds)) + + if (oldFamilyIds.length > 0) { + const familyIdsToDelete = oldFamilyIds.slice(0, 16) /* limit to 16 families per execution */ + + console.log('familyIdsToDelete: ' + JSON.stringify(familyIdsToDelete)) + + await deleteFamilies({ + database, + familiyIds: familyIdsToDelete + }) + } +} + +export async function findOldFamilyIds (database: Database) { + const familyIdsWithExpiredLicenses = await database.family.findAll({ + where: { + fullVersionUntil: { + [Sequelize.Op.lt]: (Date.now() - 1000 * 60 * 60 * 24 * 90 /* 90 days */).toString(10) + } + }, + attributes: ['familyId'] + }).map((item) => item.familyId) + + if (familyIdsWithExpiredLicenses.length === 0) { + return [] + } + + const recentlyUsedFamilyIds = await database.device.findAll({ + where: { + familyId: { + [Sequelize.Op.in]: familyIdsWithExpiredLicenses + }, + lastConnectivity: { + [Sequelize.Op.lt]: (Date.now() - 1000 * 60 * 60 * 24 * 90 /* 90 days */).toString(10) + } + }, + attributes: ['familyId'] + }).map((item) => item.familyId) + + return difference(familyIdsWithExpiredLicenses, recentlyUsedFamilyIds) +}