diff --git a/packages/backend/native-utils/scylla-migration/cql/1689400417034_timeline/up.cql b/packages/backend/native-utils/scylla-migration/cql/1689400417034_timeline/up.cql index def855b795..16964e7bcf 100644 --- a/packages/backend/native-utils/scylla-migration/cql/1689400417034_timeline/up.cql +++ b/packages/backend/native-utils/scylla-migration/cql/1689400417034_timeline/up.cql @@ -216,6 +216,8 @@ CREATE TABLE home_timeline ( CREATE INDEX home_by_id ON home_timeline ("id"); +CREATE INDEX home_by_feed_user_id ON home_timeline ("feedUserId"); + CREATE TABLE reaction ( "id" text, "noteId" ascii, diff --git a/packages/backend/src/db/cql.ts b/packages/backend/src/db/cql.ts index 932b9385cf..b0f875b986 100644 --- a/packages/backend/src/db/cql.ts +++ b/packages/backend/src/db/cql.ts @@ -116,6 +116,7 @@ export const scyllaQueries = { select: { byUserAndDate: `SELECT * FROM home_timeline WHERE "feedUserId" = ? AND "createdAtDate" = ?`, byId: `SELECT * FROM home_timeline WHERE "id" = ?`, + byUser: `SELECT * FROM home_timeline WHERE "feedUserId" = ?`, }, delete: `DELETE FROM home_timeline WHERE "feedUserId" = ? AND "createdAtDate" = ? AND "createdAt" = ? AND "userId" = ?`, update: { diff --git a/packages/backend/src/queue/processors/db/delete-account.ts b/packages/backend/src/queue/processors/db/delete-account.ts index 1ce1302559..6d0f5f7271 100644 --- a/packages/backend/src/queue/processors/db/delete-account.ts +++ b/packages/backend/src/queue/processors/db/delete-account.ts @@ -46,12 +46,33 @@ export async function deleteAccount( let cursor: Note["id"] | null = null; if (scyllaClient) { + // FIXME: Cascading notes won't be deleted. Reply and renote counts will be incorrect. + const client = scyllaClient as Client; + // Clear user's home timeline + scyllaClient.eachRow( + prepared.homeTimeline.select.byUser, + [user.id], + { prepare: true }, + (_, row) => { + const timeline = parseHomeTimeline(row); + client.execute( + prepared.homeTimeline.delete, + [ + timeline.feedUserId, + timeline.createdAtDate, + timeline.createdAt, + timeline.userId, + ], + { prepare: true }, + ); + }, + ); + // Delete notes scyllaClient.eachRow( prepared.note.select.byUserId, [user.id], { prepare: true }, (_, row) => { - const client = scyllaClient as Client; const note = parseScyllaNote(row); const noteDeleteParams = [ note.createdAt, @@ -60,9 +81,11 @@ export async function deleteAccount( note.userHost ?? "local", note.visibility, ] as [Date, Date, string, string, string]; + // Delete note from global feed client.execute(prepared.note.delete, noteDeleteParams, { prepare: true, }); + // Delete note from home timelines client.eachRow( prepared.homeTimeline.select.byId, [note.id], @@ -140,7 +163,7 @@ export async function deleteAccount( } } } - logger.succ("All of notes deleted"); + logger.succ("All associated notes deleted"); } { @@ -170,7 +193,7 @@ export async function deleteAccount( } } - logger.succ("All of files deleted"); + logger.succ("All associated files deleted"); } {