fix(worker): better deletion of project
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
import { logger } from '@/utils/logger';
|
import { logger } from '@/utils/logger';
|
||||||
import { generateSalt } from '@openpanel/common/server';
|
import { TABLE_NAMES, ch, db } from '@openpanel/db';
|
||||||
import { TABLE_NAMES, ch, chQuery, db } from '@openpanel/db';
|
import type { CronQueuePayload } from '@openpanel/queue';
|
||||||
|
import type { Job } from 'bullmq';
|
||||||
import { escape } from 'sqlstring';
|
import { escape } from 'sqlstring';
|
||||||
|
|
||||||
export async function deleteProjects() {
|
export async function deleteProjects(job: Job<CronQueuePayload>) {
|
||||||
const projects = await db.project.findMany({
|
const projects = await db.project.findMany({
|
||||||
where: {
|
where: {
|
||||||
deleteAt: {
|
deleteAt: {
|
||||||
@@ -24,16 +25,33 @@ export async function deleteProjects() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.SELF_HOSTED) {
|
logger.info('Deleting projects', {
|
||||||
|
projects,
|
||||||
|
});
|
||||||
|
|
||||||
|
projects.forEach((project) => {
|
||||||
|
job.log(`Delete project: "${project.id}"`);
|
||||||
|
});
|
||||||
|
|
||||||
|
const where = `project_id IN (${projects.map((project) => escape(project.id)).join(',')})`;
|
||||||
|
const tables = [
|
||||||
|
TABLE_NAMES.events,
|
||||||
|
TABLE_NAMES.profiles,
|
||||||
|
TABLE_NAMES.events_bots,
|
||||||
|
TABLE_NAMES.sessions,
|
||||||
|
TABLE_NAMES.cohort_events_mv,
|
||||||
|
TABLE_NAMES.dau_mv,
|
||||||
|
TABLE_NAMES.event_names_mv,
|
||||||
|
TABLE_NAMES.event_property_values_mv,
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const table of tables) {
|
||||||
|
const query = process.env.SELF_HOSTED
|
||||||
|
? `ALTER TABLE ${table} DELETE WHERE ${where};`
|
||||||
|
: `ALTER TABLE ${table}_replicated ON CLUSTER '{cluster}' DELETE WHERE ${where};`;
|
||||||
|
|
||||||
await ch.command({
|
await ch.command({
|
||||||
query: `DELETE FROM ${TABLE_NAMES.events} WHERE project_id IN (${projects.map((project) => escape(project.id)).join(',')});`,
|
query,
|
||||||
clickhouse_settings: {
|
|
||||||
lightweight_deletes_sync: 0,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await ch.command({
|
|
||||||
query: `DELETE FROM ${TABLE_NAMES.events}_replicated ON CLUSTER '{cluster}' WHERE project_id IN (${projects.map((project) => escape(project.id)).join(',')});`,
|
|
||||||
clickhouse_settings: {
|
clickhouse_settings: {
|
||||||
lightweight_deletes_sync: 0,
|
lightweight_deletes_sync: 0,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export async function cronJob(job: Job<CronQueuePayload>) {
|
|||||||
return await ping();
|
return await ping();
|
||||||
}
|
}
|
||||||
case 'deleteProjects': {
|
case 'deleteProjects': {
|
||||||
return await deleteProjects();
|
return await deleteProjects(job);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "dashboards" DROP CONSTRAINT "dashboards_organizationId_fkey";
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "integrations" DROP CONSTRAINT "integrations_organizationId_fkey";
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "invites" DROP CONSTRAINT "invites_createdById_fkey";
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "notifications" DROP CONSTRAINT "notifications_integrationId_fkey";
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "notifications" DROP CONSTRAINT "notifications_notificationRuleId_fkey";
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "reports" DROP CONSTRAINT "reports_dashboardId_fkey";
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "reset_password" DROP CONSTRAINT "reset_password_accountId_fkey";
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "shares" DROP CONSTRAINT "shares_organizationId_fkey";
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "invites" ADD CONSTRAINT "invites_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "dashboards" ADD CONSTRAINT "dashboards_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "reports" ADD CONSTRAINT "reports_dashboardId_fkey" FOREIGN KEY ("dashboardId") REFERENCES "dashboards"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "shares" ADD CONSTRAINT "shares_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "notifications" ADD CONSTRAINT "notifications_integrationId_fkey" FOREIGN KEY ("integrationId") REFERENCES "integrations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "notifications" ADD CONSTRAINT "notifications_notificationRuleId_fkey" FOREIGN KEY ("notificationRuleId") REFERENCES "notification_rules"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "integrations" ADD CONSTRAINT "integrations_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "reset_password" ADD CONSTRAINT "reset_password_accountId_fkey" FOREIGN KEY ("accountId") REFERENCES "accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
@@ -36,7 +36,7 @@ model Organization {
|
|||||||
projects Project[]
|
projects Project[]
|
||||||
members Member[]
|
members Member[]
|
||||||
createdByUserId String?
|
createdByUserId String?
|
||||||
createdBy User? @relation(name: "organizationCreatedBy", fields: [createdByUserId], references: [id])
|
createdBy User? @relation(name: "organizationCreatedBy", fields: [createdByUserId], references: [id], onDelete: SetNull)
|
||||||
ProjectAccess ProjectAccess[]
|
ProjectAccess ProjectAccess[]
|
||||||
Client Client[]
|
Client Client[]
|
||||||
Dashboard Dashboard[]
|
Dashboard Dashboard[]
|
||||||
@@ -129,7 +129,7 @@ model Member {
|
|||||||
userId String?
|
userId String?
|
||||||
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
invitedById String?
|
invitedById String?
|
||||||
invitedBy User? @relation("invitedBy", fields: [invitedById], references: [id])
|
invitedBy User? @relation("invitedBy", fields: [invitedById], references: [id], onDelete: SetNull)
|
||||||
organizationId String
|
organizationId String
|
||||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||||
meta Json?
|
meta Json?
|
||||||
@@ -142,7 +142,7 @@ model Member {
|
|||||||
model Invite {
|
model Invite {
|
||||||
id String @id
|
id String @id
|
||||||
email String
|
email String
|
||||||
createdBy User @relation(fields: [createdById], references: [id])
|
createdBy User @relation(fields: [createdById], references: [id], onDelete: Cascade)
|
||||||
createdById String
|
createdById String
|
||||||
organizationId String
|
organizationId String
|
||||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||||
@@ -263,7 +263,7 @@ enum ChartType {
|
|||||||
model Dashboard {
|
model Dashboard {
|
||||||
id String @id @default(dbgenerated("gen_random_uuid()"))
|
id String @id @default(dbgenerated("gen_random_uuid()"))
|
||||||
name String
|
name String
|
||||||
organization Organization @relation(fields: [organizationId], references: [id])
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||||
organizationId String
|
organizationId String
|
||||||
projectId String
|
projectId String
|
||||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||||
@@ -302,7 +302,7 @@ model Report {
|
|||||||
funnelWindow Float?
|
funnelWindow Float?
|
||||||
|
|
||||||
dashboardId String
|
dashboardId String
|
||||||
dashboard Dashboard @relation(fields: [dashboardId], references: [id])
|
dashboard Dashboard @relation(fields: [dashboardId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @default(now()) @updatedAt
|
updatedAt DateTime @default(now()) @updatedAt
|
||||||
@@ -314,7 +314,7 @@ model ShareOverview {
|
|||||||
id String @unique
|
id String @unique
|
||||||
projectId String @unique
|
projectId String @unique
|
||||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||||
organization Organization @relation(fields: [organizationId], references: [id])
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||||
organizationId String
|
organizationId String
|
||||||
public Boolean @default(false)
|
public Boolean @default(false)
|
||||||
password String?
|
password String?
|
||||||
@@ -389,10 +389,10 @@ model Notification {
|
|||||||
updatedAt DateTime @default(now()) @updatedAt
|
updatedAt DateTime @default(now()) @updatedAt
|
||||||
sendToApp Boolean @default(false)
|
sendToApp Boolean @default(false)
|
||||||
sendToEmail Boolean @default(false)
|
sendToEmail Boolean @default(false)
|
||||||
integration Integration? @relation(fields: [integrationId], references: [id])
|
integration Integration? @relation(fields: [integrationId], references: [id], onDelete: Cascade)
|
||||||
integrationId String? @db.Uuid
|
integrationId String? @db.Uuid
|
||||||
notificationRuleId String? @db.Uuid
|
notificationRuleId String? @db.Uuid
|
||||||
notificationRule NotificationRule? @relation(fields: [notificationRuleId], references: [id])
|
notificationRule NotificationRule? @relation(fields: [notificationRuleId], references: [id], onDelete: Cascade)
|
||||||
/// [IPrismaNotificationPayload]
|
/// [IPrismaNotificationPayload]
|
||||||
payload Json?
|
payload Json?
|
||||||
|
|
||||||
@@ -404,7 +404,7 @@ model Integration {
|
|||||||
name String
|
name String
|
||||||
/// [IPrismaIntegrationConfig]
|
/// [IPrismaIntegrationConfig]
|
||||||
config Json
|
config Json
|
||||||
organization Organization @relation(fields: [organizationId], references: [id])
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||||
organizationId String
|
organizationId String
|
||||||
notificationRules NotificationRule[]
|
notificationRules NotificationRule[]
|
||||||
notifications Notification[]
|
notifications Notification[]
|
||||||
@@ -417,7 +417,7 @@ model Integration {
|
|||||||
model ResetPassword {
|
model ResetPassword {
|
||||||
id String @id
|
id String @id
|
||||||
accountId String
|
accountId String
|
||||||
account Account @relation(fields: [accountId], references: [id])
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
||||||
expiresAt DateTime
|
expiresAt DateTime
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @default(now()) @updatedAt
|
updatedAt DateTime @default(now()) @updatedAt
|
||||||
|
|||||||
Reference in New Issue
Block a user