diff --git a/package.json b/package.json index 6f8aa3b160..199205db48 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "start:test": "pnpm --filter backend run start:test", "init": "pnpm run migrate", "migrate": "pnpm --filter backend run migrate", - "migrate:scylla": "pnpm --filter backend run migrate:scylla", + "scylla:migrate": "pnpm --filter native-utils run scylla:migrate", + "scylla:setup": "pnpm --filter native-utils run scylla:setup && pnpm run scylla:migrate", "revertmigration": "pnpm --filter backend run revertmigration", "migrateandstart": "pnpm run migrate && pnpm run start", "gulp": "gulp build", diff --git a/packages/backend/native-utils/package.json b/packages/backend/native-utils/package.json index 98b4e6fec9..2a87cfbd42 100644 --- a/packages/backend/native-utils/package.json +++ b/packages/backend/native-utils/package.json @@ -38,6 +38,8 @@ "build:napi": "napi build --features napi --platform --release ./built/", "build:migration": "cargo build --locked --release --manifest-path ./migration/Cargo.toml && cp -v ./target/release/migration ./built/migration", "build:debug": "napi build --features napi --platform ./built/ && cargo build --locked --manifest-path ./migration/Cargo.toml && cp -v ./target/debug/migration ./built/migration", + "scylla:migrate": "cargo run --release --locked --manifest-path ./scylla-migration/Cargo.toml -- -d ./scylla-migration/cql -c ../../../.config/default.yml up", + "scylla:setup": "cargo run --release --locked --manifest-path ./scylla-migration/Cargo.toml -- -d ./scylla-migration/cql -c ../../../.config/default.yml setup", "prepublishOnly": "napi prepublish -t npm", "test": "pnpm run cargo:test && pnpm run build:napi && ava", "universal": "napi universal", diff --git a/packages/backend/native-utils/scylla-migration/src/setup.rs b/packages/backend/native-utils/scylla-migration/src/setup.rs index a32b5389b8..c67273533f 100644 --- a/packages/backend/native-utils/scylla-migration/src/setup.rs +++ b/packages/backend/native-utils/scylla-migration/src/setup.rs @@ -57,7 +57,7 @@ impl Initializer { .await?; } - let tables = vec!["note", "note_edit", "poll", "poll_vote", "notification"]; + let tables = vec!["note_reaction", "note_edit", "poll", "poll_vote", "notification", "note"]; for table in tables { sqlx::query(&format!("DROP TABLE {}", table)) .execute(&mut conn) diff --git a/packages/backend/package.json b/packages/backend/package.json index d0cb4deec6..f37f57b92e 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -9,7 +9,6 @@ "migrate": "pnpm run migrate:typeorm && pnpm run migrate:cargo", "migrate:typeorm": "typeorm migration:run -d ormconfig.js", "migrate:cargo": "./native-utils/built/migration up", - "migrate:scylla": "cargo run --release --locked --manifest-path ./native-utils/scylla-migration/Cargo.toml -- -d ./native-utils/scylla-migration/cql -c ../../.config/default.yml up", "revertmigration": "pnpm run revertmigration:cargo && pnpm run revertmigration:typeorm", "revertmigration:typeorm": "typeorm migration:revert -d ormconfig.js", "revertmigration:cargo": "./native-utils/built/migration down", diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index 41bd251bd0..629cf5dbad 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -7,7 +7,6 @@ import type { Packed } from "@/misc/schema.js"; import type { Promiseable } from "@/prelude/await-all.js"; import { awaitAll } from "@/prelude/await-all.js"; import { populateEmojis } from "@/misc/populate-emojis.js"; -import { getAntennas } from "@/misc/antenna-cache.js"; import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from "@/const.js"; import { Cache } from "@/misc/cache.js"; import { db } from "@/db/postgre.js"; @@ -296,6 +295,11 @@ export const UserRepository = db.getRepository(User).extend({ }, async getHasUnreadNotification(userId: User["id"]): Promise { + if (scyllaClient) { + // FIXME: all notifications are automatically read at the moment + return false; + } + const mute = await Mutings.findBy({ muterId: userId, }); diff --git a/packages/backend/src/server/api/common/read-notification.ts b/packages/backend/src/server/api/common/read-notification.ts index 1fb1d642fe..fa582ab6e0 100644 --- a/packages/backend/src/server/api/common/read-notification.ts +++ b/packages/backend/src/server/api/common/read-notification.ts @@ -4,12 +4,14 @@ import { pushNotification } from "@/services/push-notification.js"; import type { User } from "@/models/entities/user.js"; import type { Notification } from "@/models/entities/notification.js"; import { Notifications, Users } from "@/models/index.js"; +import { scyllaClient } from "@/db/scylla.js"; export async function readNotification( userId: User["id"], notificationIds: Notification["id"][], ) { - if (notificationIds.length === 0) return; + // FIXME: all notifications are automatically read at the moment + if (notificationIds.length === 0 || scyllaClient) return; // Update documents const result = await Notifications.update( @@ -34,6 +36,11 @@ export async function readNotificationByQuery( userId: User["id"], query: Record, ) { + if (scyllaClient) { + // FIXME: all notifications are automatically read at the moment + return; + } + const notificationIds = await Notifications.findBy({ ...query, notifieeId: userId, diff --git a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts index 984bc0789e..502d6f583c 100644 --- a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts @@ -5,6 +5,7 @@ import type { User } from "@/models/entities/user.js"; import { insertModerationLog } from "@/services/insert-moderation-log.js"; import { doPostSuspend } from "@/services/suspend-user.js"; import { publishUserEvent } from "@/services/stream.js"; +import { scyllaClient } from "@/db/scylla.js"; export const meta = { tags: ["admin"], @@ -75,6 +76,11 @@ async function unFollowAll(follower: User) { } async function readAllNotify(notifier: User) { + if (scyllaClient) { + // FIXME: all notifications are automatically read at the moment + return; + } + await Notifications.update( { notifierId: notifier.id, diff --git a/packages/backend/src/server/api/endpoints/notes.ts b/packages/backend/src/server/api/endpoints/notes.ts index 61ac8f4048..5ce2653887 100644 --- a/packages/backend/src/server/api/endpoints/notes.ts +++ b/packages/backend/src/server/api/endpoints/notes.ts @@ -41,7 +41,9 @@ export default define(meta, paramDef, async (ps) => { ps.untilId, ) .andWhere("note.visibility = 'public'") - .andWhere("note.localOnly = FALSE"); + .andWhere("note.localOnly = FALSE") + .leftJoinAndSelect("note.reply", "reply") + .leftJoinAndSelect("note.renote", "renote"); if (ps.local) { query.andWhere("note.userHost IS NULL"); diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index 47c1e13812..c8362f21df 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -46,17 +46,6 @@ export default define(meta, paramDef, async (ps, user) => { .andWhere("note.score > 0") .andWhere("note.createdAt > :date", { date: new Date(Date.now() - day) }) .andWhere("note.visibility = 'public'") - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); switch (ps.origin) { case "local": diff --git a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts index 646be67f6e..f400e0ff91 100644 --- a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts @@ -178,7 +178,9 @@ export default define(meta, paramDef, async (ps, user) => { ps.untilDate, ) .andWhere("note.visibility = 'public'") - .andWhere("note.channelId IS NULL"); + .andWhere("note.channelId IS NULL") + .leftJoinAndSelect("note.reply", "reply") + .leftJoinAndSelect("note.renote", "renote"); generateRepliesQuery(query, ps.withReplies, user); if (user) { diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts index 4baf610eab..80d2cddea2 100644 --- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -218,6 +218,8 @@ export default define(meta, paramDef, async (ps, user) => { ).orWhere("(note.visibility = 'public') AND (note.userHost IS NULL)"); }), ) + .leftJoinAndSelect("note.reply", "reply") + .leftJoinAndSelect("note.renote", "renote") .setParameters(followingQuery.getParameters()); generateChannelQuery(query, user); diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts index fcd131eabc..dbab2f019b 100644 --- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts @@ -206,7 +206,10 @@ export default define(meta, paramDef, async (ps, user) => { ps.untilId, ps.sinceDate, ps.untilDate, - ).andWhere("(note.visibility = 'public') AND (note.userHost IS NULL)"); + ) + .andWhere("(note.visibility = 'public') AND (note.userHost IS NULL)") + .leftJoinAndSelect("note.reply", "reply") + .leftJoinAndSelect("note.renote", "renote"); generateChannelQuery(query, user); generateRepliesQuery(query, ps.withReplies, user); diff --git a/packages/backend/src/server/api/endpoints/notes/renotes.ts b/packages/backend/src/server/api/endpoints/notes/renotes.ts index 56213dd223..b5385d4e9b 100644 --- a/packages/backend/src/server/api/endpoints/notes/renotes.ts +++ b/packages/backend/src/server/api/endpoints/notes/renotes.ts @@ -133,7 +133,10 @@ export default define(meta, paramDef, async (ps, user) => { Notes.createQueryBuilder("note"), ps.sinceId, ps.untilId, - ).andWhere("note.renoteId = :renoteId", { renoteId: note.id }); + ) + .andWhere("note.renoteId = :renoteId", { renoteId: note.id }) + .leftJoinAndSelect("note.reply", "reply") + .leftJoinAndSelect("note.renote", "renote"); if (ps.userId) { query.andWhere("note.userId = :userId", { userId: ps.userId }); diff --git a/packages/backend/src/server/api/endpoints/notes/show.ts b/packages/backend/src/server/api/endpoints/notes/show.ts index e674664100..8c5f91c5c1 100644 --- a/packages/backend/src/server/api/endpoints/notes/show.ts +++ b/packages/backend/src/server/api/endpoints/notes/show.ts @@ -2,7 +2,6 @@ import { Notes } from "@/models/index.js"; import define from "../../define.js"; import { getNote } from "../../common/getters.js"; import { ApiError } from "../../error.js"; -import { scyllaClient } from "@/db/scylla.js"; export const meta = { tags: ["notes"], diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts index 2794ead481..c95aba45f4 100644 --- a/packages/backend/src/server/api/endpoints/notes/timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts @@ -197,6 +197,8 @@ export default define(meta, paramDef, async (ps, user) => { qb.orWhere(`note.userId IN (${followingQuery.getQuery()})`); }), ) + .leftJoinAndSelect("note.reply", "reply") + .leftJoinAndSelect("note.renote", "renote") .setParameters(followingQuery.getParameters()); generateChannelQuery(query, user); diff --git a/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts b/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts index e0888ad752..663157f109 100644 --- a/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts +++ b/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts @@ -2,6 +2,7 @@ import { publishMainStream } from "@/services/stream.js"; import { pushNotification } from "@/services/push-notification.js"; import { Notifications } from "@/models/index.js"; import define from "../../define.js"; +import { scyllaClient } from "@/db/scylla.js"; export const meta = { tags: ["notifications", "account"], @@ -18,16 +19,18 @@ export const paramDef = { } as const; export default define(meta, paramDef, async (ps, user) => { - // Update documents - await Notifications.update( - { - notifieeId: user.id, - isRead: false, - }, - { - isRead: true, - }, - ); + if (!scyllaClient) { + // Update documents + await Notifications.update( + { + notifieeId: user.id, + isRead: false, + }, + { + isRead: true, + }, + ); + } // 全ての通知を読みましたよというイベントを発行 publishMainStream(user.id, "readAllNotifications"); diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index 674ace90db..3aff0a65ed 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -176,7 +176,10 @@ export default define(meta, paramDef, async (ps, me) => { ps.untilId, ps.sinceDate, ps.untilDate, - ).andWhere("note.userId = :userId", { userId: user.id }); + ) + .andWhere("note.userId = :userId", { userId: user.id }) + .leftJoinAndSelect("note.reply", "reply") + .leftJoinAndSelect("note.renote", "renote"); generateVisibilityQuery(query, me); if (me) { diff --git a/packages/backend/src/services/note/read.ts b/packages/backend/src/services/note/read.ts index 205edafad2..675a8d54b7 100644 --- a/packages/backend/src/services/note/read.ts +++ b/packages/backend/src/services/note/read.ts @@ -6,6 +6,7 @@ import { Not, IsNull, In } from "typeorm"; import type { Channel } from "@/models/entities/channel.js"; import { readNotificationByQuery } from "@/server/api/common/read-notification.js"; import type { Packed } from "@/misc/schema.js"; +import { scyllaClient } from "@/db/scylla.js"; /** * Mark notes as read @@ -18,6 +19,11 @@ export default async function ( followingChannels: Set; }, ) { + if (scyllaClient) { + // FIXME: all notes are automatically read at the moment + return; + } + const followingChannels = info?.followingChannels ? info.followingChannels : new Set(