add queries

This commit is contained in:
Namekuji 2023-07-23 22:29:38 -04:00
parent 61da2a2e84
commit e715b918d5
No known key found for this signature in database
GPG key ID: 1D62332C07FBA532
3 changed files with 114 additions and 50 deletions

View file

@ -1,14 +1,14 @@
CREATE TYPE IF NOT EXISTS drive_file ( CREATE TYPE IF NOT EXISTS drive_file (
id ascii, id ascii,
type ascii, type ascii,
created_at timestamp, createdAt timestamp,
name text, name text,
comment text, comment text,
blurhash text, blurhash text,
url text, url text,
thumbnail_url text, thumbnailUrl text,
is_sensitive boolean, isSensitive boolean,
is_link boolean, isLink boolean,
md5 ascii, md5 ascii,
size int, size int,
width int, width int,
@ -19,7 +19,7 @@ CREATE TYPE IF NOT EXISTS note_edit_history (
content text, content text,
cw text, cw text,
files set<frozen<drive_file>>, files set<frozen<drive_file>>,
updated_at timestamp, updatedAt timestamp,
); );
CREATE TYPE IF NOT EXISTS emoji ( CREATE TYPE IF NOT EXISTS emoji (
@ -30,36 +30,36 @@ CREATE TYPE IF NOT EXISTS emoji (
); );
CREATE TABLE IF NOT EXISTS note ( -- Models timeline CREATE TABLE IF NOT EXISTS note ( -- Models timeline
created_at_date date, -- For partitioning createdAtDate date, -- For partitioning
created_at timestamp, createdAt timestamp,
id ascii, -- Post id ascii, -- Post
visibility ascii, visibility ascii,
content text, content text,
name text, name text,
cw text, cw text,
local_only boolean, localOnly boolean,
renote_count int, renoteCount int,
replies_count int, repliesCount int,
uri text, uri text,
url text, url text,
score int, score int,
files set<frozen<drive_file>>, files set<frozen<drive_file>>,
visible_users set<ascii>, visibleUsersId set<ascii>,
mentions set<ascii>, mentions set<ascii>,
emojis set<frozen<emoji>>, emojis set<frozen<emoji>>,
tags set<text>, tags set<text>,
has_poll boolean, hasPoll boolean,
thread_id ascii, threadId ascii,
channel_id ascii, -- Channel channelId ascii, -- Channel
channel_name text, channelName text,
user_id ascii, -- User userId ascii, -- User
reply_id ascii, -- Reply replyId ascii, -- Reply
renote_id ascii, -- Boost renoteId ascii, -- Boost
note_edit set<frozen<note_edit_history>>, -- Edit History
updated_at timestamp,
reactions map<text, int>, reactions map<text, int>,
reaction_emojis map<text, frozen<emoji>>, reactionEmojis map<text, frozen<emoji>>,
PRIMARY KEY (created_at_date, created_at) noteEdit set<frozen<note_edit_history>>, -- Edit History
updatedAt timestamp,
PRIMARY KEY (createdAtDate, createdAt)
) WITH CLUSTERING ORDER BY (created_at DESC); ) WITH CLUSTERING ORDER BY (created_at DESC);
CREATE INDEX IF NOT EXISTS note_by_id ON note (id); 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 CREATE MATERIALIZED VIEW IF NOT EXISTS note_by_user_id AS
SELECT * FROM note SELECT * FROM note
WHERE user_id IS NOT NULL WHERE userId IS NOT NULL
AND created_at IS NOT NULL AND createdAt IS NOT NULL
AND created_at_date IS NOT NULL AND createdAtDate IS NOT NULL
PRIMARY KEY (user_id, created_at, created_at_date) PRIMARY KEY (userId, createdAt, createdAtDate)
WITH CLUSTERING ORDER BY (created_at DESC); WITH CLUSTERING ORDER BY (createdAt DESC);
CREATE TABLE IF NOT EXISTS reaction ( CREATE TABLE IF NOT EXISTS reaction (
note_id ascii, noteId ascii,
created_at timestamp, createdAt timestamp,
user_id ascii, userId ascii,
reaction frozen<emoji>, reaction frozen<emoji>,
PRIMARY KEY (note_id, created_at, user_id) PRIMARY KEY (noteId, createdAt, userId)
); );

View file

@ -1,4 +1,5 @@
import config from "@/config/index.js"; import config from "@/config/index.js";
import { DriveFile } from "@/models/entities/drive-file.js";
import { Client } from "cassandra-driver"; import { Client } from "cassandra-driver";
function newClient(): Client | null { function newClient(): Client | null {
@ -17,46 +18,63 @@ export const scyllaClient = newClient();
export const prepared = { export const prepared = {
timeline: { timeline: {
insert: `INSERT INTO note ( insert: `INSERT INTO note (
created_at_date, createdAtDate,
created_at, createdAt,
id, id,
visibility, visibility,
content, content,
name, name,
cw, cw,
local_only, localOnly,
renote_count, renoteCount,
replies_count, repliesCount,
uri, uri,
url, url,
score, score,
files, files,
visible_users, visibleUsersId,
mentions, mentions,
emojis, emojis,
tags, tags,
has_poll, hasPoll,
thread_id, threadId,
channel_id, channelId,
channel_name, channelName,
user_id, userId,
user_id, userId,
reply_id, replyId,
renote_id, renoteId,
note_edit,
updated_at,
reactions, reactions,
reaction_emojis reactionEmojis
noteEdit,
updatedAt,
) )
VALUES VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
select: { 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 ?", byId: "SELECT * FROM note WHERE id IN ?",
byUri: "SELECT * FROM note WHERE uri = ?", byUri: "SELECT * FROM note WHERE uri = ?",
byUrl: "SELECT * FROM note WHERE url = ?", 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 ?", 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;
}

View file

@ -67,6 +67,9 @@ import { shouldSilenceInstance } from "@/misc/should-block-instance.js";
import meilisearch from "../../db/meilisearch.js"; import meilisearch from "../../db/meilisearch.js";
import { redisClient } from "@/db/redis.js"; import { redisClient } from "@/db/redis.js";
import { Mutex } from "redis-semaphore"; 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< const mutedWordsCache = new Cache<
{ userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[] { userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[]
@ -758,6 +761,49 @@ async function insertNote(
// 投稿を作成 // 投稿を作成
try { 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) { if (insert.hasPoll) {
// Start transaction // Start transaction
await db.transaction(async (transactionalEntityManager) => { await db.transaction(async (transactionalEntityManager) => {