fix filter delete notes out from timeliens
This commit is contained in:
parent
86ccb51fd0
commit
2a05d8ce12
5 changed files with 61 additions and 13 deletions
|
@ -2,6 +2,7 @@ DROP MATERIALIZED VIEW IF EXISTS reaction_by_id;
|
||||||
DROP MATERIALIZED VIEW IF EXISTS reaction_by_userid;
|
DROP MATERIALIZED VIEW IF EXISTS reaction_by_userid;
|
||||||
DROP INDEX IF EXISTS reaction_by_id;
|
DROP INDEX IF EXISTS reaction_by_id;
|
||||||
DROP TABLE IF EXISTS reaction;
|
DROP TABLE IF EXISTS reaction;
|
||||||
|
DROP TABLE IF EXISTS deleted_note;
|
||||||
DROP TABLE IF EXISTS home_timeline;
|
DROP TABLE IF EXISTS home_timeline;
|
||||||
DROP MATERIALIZED VIEW IF EXISTS local_timeline;
|
DROP MATERIALIZED VIEW IF EXISTS local_timeline;
|
||||||
DROP MATERIALIZED VIEW IF EXISTS global_timeline;
|
DROP MATERIALIZED VIEW IF EXISTS global_timeline;
|
||||||
|
|
|
@ -168,9 +168,15 @@ CREATE TABLE IF NOT EXISTS home_timeline (
|
||||||
"reactions" map<text, int>, -- Reactions
|
"reactions" map<text, int>, -- Reactions
|
||||||
"noteEdit" set<frozen<note_edit_history>>, -- Edit History
|
"noteEdit" set<frozen<note_edit_history>>, -- Edit History
|
||||||
"updatedAt" timestamp,
|
"updatedAt" timestamp,
|
||||||
PRIMARY KEY (("feedUserId", "createdAtDate"), "createdAt")
|
PRIMARY KEY (("feedUserId", "createdAtDate"), "createdAt", "userId")
|
||||||
) WITH CLUSTERING ORDER BY ("createdAt" DESC);
|
) WITH CLUSTERING ORDER BY ("createdAt" DESC);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS deleted_note (
|
||||||
|
"noteId" ascii,
|
||||||
|
"deletedAt" timestamp,
|
||||||
|
PRIMARY KEY ("noteId", "deletedAt")
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS reaction (
|
CREATE TABLE IF NOT EXISTS reaction (
|
||||||
"id" text,
|
"id" text,
|
||||||
"noteId" ascii,
|
"noteId" ascii,
|
||||||
|
|
|
@ -49,7 +49,7 @@ export const scyllaQueries = {
|
||||||
byUserId: `SELECT * FROM note_by_user_id WHERE "userId" IN ?`,
|
byUserId: `SELECT * FROM note_by_user_id WHERE "userId" IN ?`,
|
||||||
byRenoteId: `SELECT * FROM note_by_renote_id WHERE "renoteId" = ?`,
|
byRenoteId: `SELECT * FROM note_by_renote_id WHERE "renoteId" = ?`,
|
||||||
},
|
},
|
||||||
delete: `DELETE FROM note WHERE "createdAtDate" = ? AND "createdAt" = ? AND "userId" = ?`,
|
delete: `DELETE FROM note WHERE "createdAtDate" = ? AND "createdAt" = ? AND "userId" = ? AND "userHost" = ? AND "visibility" = ?`,
|
||||||
update: {
|
update: {
|
||||||
renoteCount: `UPDATE note SET
|
renoteCount: `UPDATE note SET
|
||||||
"renoteCount" = ?,
|
"renoteCount" = ?,
|
||||||
|
@ -122,6 +122,10 @@ export const scyllaQueries = {
|
||||||
byDate: `SELECT * FROM global_timeline WHERE "createdAtDate" = ?`,
|
byDate: `SELECT * FROM global_timeline WHERE "createdAtDate" = ?`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
deletedNote: {
|
||||||
|
insert: `INSERT INTO deleted_note ("noteId", "deletedAt") VALUES (?, ?)`,
|
||||||
|
select: `SELECT "noteId" FROM deleted_note`,
|
||||||
|
},
|
||||||
reaction: {
|
reaction: {
|
||||||
insert: `INSERT INTO reaction
|
insert: `INSERT INTO reaction
|
||||||
("id", "noteId", "userId", "reaction", "emoji", "createdAt")
|
("id", "noteId", "userId", "reaction", "emoji", "createdAt")
|
||||||
|
|
|
@ -155,13 +155,30 @@ export function parseScyllaNote(row: types.Row): ScyllaNote {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DeletedNote {
|
||||||
|
noteId: string;
|
||||||
|
deletedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseDeletedNote(row: types.Row): DeletedNote {
|
||||||
|
return {
|
||||||
|
noteId: row.get("noteId"),
|
||||||
|
deletedAt: row.get("deletedAt"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export interface ScyllaNoteReaction extends NoteReaction {
|
export interface ScyllaNoteReaction extends NoteReaction {
|
||||||
emoji: PopulatedEmoji;
|
emoji: PopulatedEmoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QUERY_LIMIT = 1000; // TODO: should this be configurable?
|
const QUERY_LIMIT = 1000; // TODO: should this be configurable?
|
||||||
|
|
||||||
export type TimelineKind = "home" | "local" | "recommended" | "global" | "renotes";
|
export type TimelineKind =
|
||||||
|
| "home"
|
||||||
|
| "local"
|
||||||
|
| "recommended"
|
||||||
|
| "global"
|
||||||
|
| "renotes";
|
||||||
|
|
||||||
export function parseScyllaReaction(row: types.Row): ScyllaNoteReaction {
|
export function parseScyllaReaction(row: types.Row): ScyllaNoteReaction {
|
||||||
return {
|
return {
|
||||||
|
@ -177,16 +194,17 @@ export function parseScyllaReaction(row: types.Row): ScyllaNoteReaction {
|
||||||
export function prepareNoteQuery(
|
export function prepareNoteQuery(
|
||||||
kind: TimelineKind,
|
kind: TimelineKind,
|
||||||
ps: {
|
ps: {
|
||||||
untilId?: string;
|
untilId?: string;
|
||||||
untilDate?: number;
|
untilDate?: number;
|
||||||
sinceId?: string;
|
sinceId?: string;
|
||||||
sinceDate?: number;
|
sinceDate?: number;
|
||||||
}): { query: string; untilDate: Date; sinceDate: Date | null } {
|
},
|
||||||
|
): { query: string; untilDate: Date; sinceDate: Date | null } {
|
||||||
const queryParts: string[] = [];
|
const queryParts: string[] = [];
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case "home":
|
case "home":
|
||||||
queryParts.push(prepared.homeTimeline.select.byUserAndDate)
|
queryParts.push(prepared.homeTimeline.select.byUserAndDate);
|
||||||
break;
|
break;
|
||||||
case "local":
|
case "local":
|
||||||
queryParts.push(prepared.localTimeline.select.byDate);
|
queryParts.push(prepared.localTimeline.select.byDate);
|
||||||
|
@ -283,7 +301,18 @@ export async function execNotePaginationQuery(
|
||||||
|
|
||||||
if (result.rowLength > 0) {
|
if (result.rowLength > 0) {
|
||||||
const notes = result.rows.map(parseScyllaNote);
|
const notes = result.rows.map(parseScyllaNote);
|
||||||
foundNotes.push(...(filter ? await filter(notes) : notes));
|
const candidates = filter ? await filter(notes) : notes;
|
||||||
|
// foundNotes.push(...(filter ? await filter(notes) : notes));
|
||||||
|
const deletedNotes = await scyllaClient
|
||||||
|
.execute(`${prepared.deletedNote.select} WHERE "noteId" IN ?`, [
|
||||||
|
candidates.map(({ id }) => id),
|
||||||
|
])
|
||||||
|
.then((result) =>
|
||||||
|
result.rows.map((row) => parseDeletedNote(row).noteId),
|
||||||
|
);
|
||||||
|
foundNotes.push(
|
||||||
|
...candidates.filter((note) => !deletedNotes.includes(note.id)),
|
||||||
|
);
|
||||||
untilDate = notes[notes.length - 1].createdAt;
|
untilDate = notes[notes.length - 1].createdAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,9 +119,17 @@ export default async function (
|
||||||
|
|
||||||
if (scyllaClient) {
|
if (scyllaClient) {
|
||||||
const date = new Date(note.createdAt.getTime());
|
const date = new Date(note.createdAt.getTime());
|
||||||
await scyllaClient.execute(prepared.note.delete, [date, date, note.userId], {
|
await scyllaClient.execute(
|
||||||
prepare: true,
|
prepared.note.delete,
|
||||||
});
|
[date, date, note.userId, note.userHost ?? "local", note.visibility],
|
||||||
|
{
|
||||||
|
prepare: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await scyllaClient.execute(prepared.deletedNote.insert, [
|
||||||
|
note.id,
|
||||||
|
new Date(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Notes.delete({
|
await Notes.delete({
|
||||||
|
|
Loading…
Reference in a new issue