From e715b918d5bf3559655bad3746c2f2178575cdd0 Mon Sep 17 00:00:00 2001 From: Namekuji Date: Sun, 23 Jul 2023 22:29:38 -0400 Subject: [PATCH] add queries --- .../cql/1689400417034_timeline/up.cql | 62 +++++++++---------- packages/backend/src/db/scylla.ts | 56 +++++++++++------ packages/backend/src/services/note/create.ts | 46 ++++++++++++++ 3 files changed, 114 insertions(+), 50 deletions(-) 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 bfcebd6319..d5c6a10a27 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 @@ -1,14 +1,14 @@ CREATE TYPE IF NOT EXISTS drive_file ( id ascii, type ascii, - created_at timestamp, + createdAt timestamp, name text, comment text, blurhash text, url text, - thumbnail_url text, - is_sensitive boolean, - is_link boolean, + thumbnailUrl text, + isSensitive boolean, + isLink boolean, md5 ascii, size int, width int, @@ -19,7 +19,7 @@ CREATE TYPE IF NOT EXISTS note_edit_history ( content text, cw text, files set>, - updated_at timestamp, + updatedAt timestamp, ); CREATE TYPE IF NOT EXISTS emoji ( @@ -30,36 +30,36 @@ CREATE TYPE IF NOT EXISTS emoji ( ); CREATE TABLE IF NOT EXISTS note ( -- Models timeline - created_at_date date, -- For partitioning - created_at timestamp, + createdAtDate date, -- For partitioning + createdAt timestamp, id ascii, -- Post visibility ascii, content text, name text, cw text, - local_only boolean, - renote_count int, - replies_count int, + localOnly boolean, + renoteCount int, + repliesCount int, uri text, url text, score int, files set>, - visible_users set, + visibleUsersId set, mentions set, emojis set>, tags set, - has_poll boolean, - thread_id ascii, - channel_id ascii, -- Channel - channel_name text, - user_id ascii, -- User - reply_id ascii, -- Reply - renote_id ascii, -- Boost - note_edit set>, -- Edit History - updated_at timestamp, + hasPoll boolean, + threadId ascii, + channelId ascii, -- Channel + channelName text, + userId ascii, -- User + replyId ascii, -- Reply + renoteId ascii, -- Boost reactions map, - reaction_emojis map>, - PRIMARY KEY (created_at_date, created_at) + reactionEmojis map>, + noteEdit set>, -- Edit History + updatedAt timestamp, + PRIMARY KEY (createdAtDate, createdAt) ) WITH CLUSTERING ORDER BY (created_at DESC); CREATE INDEX IF NOT EXISTS note_by_id ON note (id); @@ -68,16 +68,16 @@ CREATE INDEX IF NOT EXISTS note_by_url ON note (url); CREATE MATERIALIZED VIEW IF NOT EXISTS note_by_user_id AS SELECT * FROM note - WHERE user_id IS NOT NULL - AND created_at IS NOT NULL - AND created_at_date IS NOT NULL - PRIMARY KEY (user_id, created_at, created_at_date) - WITH CLUSTERING ORDER BY (created_at DESC); + WHERE userId IS NOT NULL + AND createdAt IS NOT NULL + AND createdAtDate IS NOT NULL + PRIMARY KEY (userId, createdAt, createdAtDate) + WITH CLUSTERING ORDER BY (createdAt DESC); CREATE TABLE IF NOT EXISTS reaction ( - note_id ascii, - created_at timestamp, - user_id ascii, + noteId ascii, + createdAt timestamp, + userId ascii, reaction frozen, - PRIMARY KEY (note_id, created_at, user_id) + PRIMARY KEY (noteId, createdAt, userId) ); diff --git a/packages/backend/src/db/scylla.ts b/packages/backend/src/db/scylla.ts index 56ee9bb016..c9941f9f9a 100644 --- a/packages/backend/src/db/scylla.ts +++ b/packages/backend/src/db/scylla.ts @@ -1,4 +1,5 @@ import config from "@/config/index.js"; +import { DriveFile } from "@/models/entities/drive-file.js"; import { Client } from "cassandra-driver"; function newClient(): Client | null { @@ -17,46 +18,63 @@ export const scyllaClient = newClient(); export const prepared = { timeline: { insert: `INSERT INTO note ( - created_at_date, - created_at, + createdAtDate, + createdAt, id, visibility, content, name, cw, - local_only, - renote_count, - replies_count, + localOnly, + renoteCount, + repliesCount, uri, url, score, files, - visible_users, + visibleUsersId, mentions, emojis, tags, - has_poll, - thread_id, - channel_id, - channel_name, - user_id, - user_id, - reply_id, - renote_id, - note_edit, - updated_at, + hasPoll, + threadId, + channelId, + channelName, + userId, + userId, + replyId, + renoteId, reactions, - reaction_emojis + reactionEmojis + noteEdit, + updatedAt, ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, select: { - byDate: "SELECT * FROM note WHERE created_at_date = ? AND created_at < ?", + byDate: "SELECT * FROM note WHERE createdAtDate = ? AND createdAt < ?", byId: "SELECT * FROM note WHERE id IN ?", byUri: "SELECT * FROM note WHERE uri = ?", byUrl: "SELECT * FROM note WHERE url = ?", - byUserId: "SELECT * FROM note WHERE user_id = ? AND created_at < ?", + byUserId: "SELECT * FROM note WHERE userId = ? AND createdAt < ?", }, delete: "DELETE FROM note WHERE id IN ?", }, } + +export interface ScyllaDriveFile { + id: string; + type: string; + createdAt: Date; + name: string; + comment: string | null; + blurhash: string | null; + url: string; + thumbnailUrl: string; + isSensitive: boolean; + isLink: boolean; + md5: string; + size: number; + width: number; + height: number; +} diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 095c75f427..0d39c6ebcb 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -67,6 +67,9 @@ import { shouldSilenceInstance } from "@/misc/should-block-instance.js"; import meilisearch from "../../db/meilisearch.js"; import { redisClient } from "@/db/redis.js"; import { Mutex } from "redis-semaphore"; +import { prepared, scyllaClient, ScyllaDriveFile } from "@/db/scylla.js"; +import { populateEmojis } from "@/misc/populate-emojis.js"; +import { decodeReaction } from "@/misc/reaction-lib.js"; const mutedWordsCache = new Cache< { userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[] @@ -758,6 +761,49 @@ async function insertNote( // 投稿を作成 try { + if (scyllaClient) { + const reactionEmojiNames = Object.keys(insert.reactions) + .filter((x) => x?.startsWith(":")) + .map((x) => decodeReaction(x).reaction) + .map((x) => x.replace(/:/g, "")); + const noteEmojis = await populateEmojis( + insert.emojis.concat(reactionEmojiNames), + user.host, + ); + await scyllaClient.execute( + prepared.timeline.insert, + [ + insert.createdAt, + insert.createdAt, + insert.id, + insert.visibility, + insert.text, + insert.name, + insert.cw, + insert.localOnly, + insert.renoteCount, + insert.repliesCount, + insert.uri, + insert.url, + insert.score, + data.files, + insert.visibleUserIds, + insert.mentions, + noteEmojis, + insert.tags, + insert.hasPoll, + insert.threadId, + data.channel?.id, + data.channel?.name, + user.id, + insert.replyId, + insert.renoteId, + null, + null, + ], + { prepare: true }, + ); + } if (insert.hasPoll) { // Start transaction await db.transaction(async (transactionalEntityManager) => {