add cache to follow and unfollow
This commit is contained in:
parent
b37717d431
commit
4b6d3e3fd6
8 changed files with 34 additions and 22 deletions
|
@ -21,7 +21,7 @@ export type Source = {
|
|||
keyspace: string;
|
||||
replicationFactor: number;
|
||||
localDataCentre: string;
|
||||
},
|
||||
};
|
||||
redis: {
|
||||
host: string;
|
||||
port: number;
|
||||
|
|
|
@ -131,17 +131,17 @@ export class Cache<T> {
|
|||
}
|
||||
}
|
||||
|
||||
export class FollowingsCache {
|
||||
export class LocalFollowingsCache {
|
||||
private myId: string;
|
||||
private key: string;
|
||||
|
||||
private constructor(userId: string) {
|
||||
this.myId = userId;
|
||||
this.key = `followings:${userId}`;
|
||||
this.key = `follow:${userId}`;
|
||||
}
|
||||
|
||||
public static async init(userId: string) {
|
||||
const cache = new FollowingsCache(userId);
|
||||
const cache = new LocalFollowingsCache(userId);
|
||||
|
||||
// Sync from DB if no relationships is cached
|
||||
if ((await redisClient.scard(cache.key)) === 0) {
|
||||
|
@ -157,12 +157,14 @@ export class FollowingsCache {
|
|||
|
||||
public async follow(...targetIds: string[]) {
|
||||
if (targetIds.length > 0) {
|
||||
// This is no-op if targets are already in cache
|
||||
await redisClient.sadd(this.key, targetIds);
|
||||
}
|
||||
}
|
||||
|
||||
public async unfollow(...targetIds: string[]) {
|
||||
if (targetIds.length > 0) {
|
||||
// This is no-op if targets are not in cache
|
||||
await redisClient.srem(this.key, targetIds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import type { Note } from "@/models/entities/note.js";
|
|||
import { Notes, Users } from "@/models/index.js";
|
||||
import { generateVisibilityQuery } from "./generate-visibility-query.js";
|
||||
import { parseScyllaNote, prepared, scyllaClient } from "@/db/scylla.js";
|
||||
import { FollowingsCache } from "@/misc/cache.js";
|
||||
import { LocalFollowingsCache } from "@/misc/cache.js";
|
||||
|
||||
/**
|
||||
* Get note for API processing, taking into account visibility.
|
||||
|
@ -29,7 +29,7 @@ export async function getNote(
|
|||
) {
|
||||
valid = true;
|
||||
} else if (me) {
|
||||
const cache = await FollowingsCache.init(me.id);
|
||||
const cache = await LocalFollowingsCache.init(me.id);
|
||||
|
||||
valid =
|
||||
candidate.userId === me.id || // my own post
|
||||
|
|
|
@ -5,6 +5,7 @@ import { getUser } from "../../common/getters.js";
|
|||
import { Followings, Users } from "@/models/index.js";
|
||||
import { IdentifiableError } from "@/misc/identifiable-error.js";
|
||||
import { HOUR } from "@/const.js";
|
||||
import { LocalFollowingsCache } from "@/misc/cache.js";
|
||||
|
||||
export const meta = {
|
||||
tags: ["following", "users"],
|
||||
|
@ -82,12 +83,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
|
||||
// Check if already following
|
||||
const exist = await Followings.exist({
|
||||
where: {
|
||||
followerId: follower.id,
|
||||
followeeId: followee.id,
|
||||
},
|
||||
});
|
||||
const cache = await LocalFollowingsCache.init(follower.id);
|
||||
const exist = await cache.isFollowing(followee.id);
|
||||
|
||||
if (exist) {
|
||||
throw new ApiError(meta.errors.alreadyFollowing);
|
||||
|
|
|
@ -4,6 +4,7 @@ import { ApiError } from "../../error.js";
|
|||
import { getUser } from "../../common/getters.js";
|
||||
import { Followings, Users } from "@/models/index.js";
|
||||
import { HOUR } from "@/const.js";
|
||||
import { LocalFollowingsCache } from "@/misc/cache.js";
|
||||
|
||||
export const meta = {
|
||||
tags: ["following", "users"],
|
||||
|
@ -69,12 +70,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
|
||||
// Check not following
|
||||
const exist = await Followings.exist({
|
||||
where: {
|
||||
followerId: follower.id,
|
||||
followeeId: followee.id,
|
||||
},
|
||||
});
|
||||
const cache = await LocalFollowingsCache.init(follower.id);
|
||||
const exist = await cache.isFollowing(followee.id);
|
||||
|
||||
if (!exist) {
|
||||
throw new ApiError(meta.errors.notFollowing);
|
||||
|
|
|
@ -28,6 +28,7 @@ import type { Packed } from "@/misc/schema.js";
|
|||
import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
||||
import { webhookDeliver } from "@/queue/index.js";
|
||||
import { shouldSilenceInstance } from "@/misc/should-block-instance.js";
|
||||
import { LocalFollowingsCache } from "@/misc/cache.js";
|
||||
|
||||
const logger = new Logger("following/create");
|
||||
|
||||
|
@ -57,7 +58,7 @@ export async function insertFollowingDoc(
|
|||
followerId: follower.id,
|
||||
followeeId: followee.id,
|
||||
|
||||
// 非正規化
|
||||
// Denormalization
|
||||
followerHost: follower.host,
|
||||
followerInbox: Users.isRemoteUser(follower) ? follower.inbox : null,
|
||||
followerSharedInbox: Users.isRemoteUser(follower)
|
||||
|
@ -81,6 +82,12 @@ export async function insertFollowingDoc(
|
|||
}
|
||||
});
|
||||
|
||||
if (Users.isLocalUser(follower)) {
|
||||
// Cache following ID set
|
||||
const cache = await LocalFollowingsCache.init(follower.id);
|
||||
await cache.follow(followee.id);
|
||||
}
|
||||
|
||||
const req = await FollowRequests.findOneBy({
|
||||
followeeId: followee.id,
|
||||
followerId: follower.id,
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
perUserFollowingChart,
|
||||
} from "@/services/chart/index.js";
|
||||
import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
||||
import { LocalFollowingsCache } from "@/misc/cache.js";
|
||||
|
||||
const logger = new Logger("following/delete");
|
||||
|
||||
|
@ -39,14 +40,17 @@ export default async function (
|
|||
});
|
||||
|
||||
if (following == null) {
|
||||
logger.warn(
|
||||
"フォロー解除がリクエストされましたがフォローしていませんでした",
|
||||
);
|
||||
logger.warn("Requested follow removal but not yet following");
|
||||
return;
|
||||
}
|
||||
|
||||
await Followings.delete(following.id);
|
||||
|
||||
if (Users.isLocalUser(follower)) {
|
||||
const cache = await LocalFollowingsCache.init(follower.id);
|
||||
await cache.unfollow(followee.id);
|
||||
}
|
||||
|
||||
decrementFollowing(follower, followee);
|
||||
|
||||
// Publish unfollow event
|
||||
|
|
|
@ -8,6 +8,7 @@ import { User } from "@/models/entities/user.js";
|
|||
import { Users, FollowRequests, Followings } from "@/models/index.js";
|
||||
import { decrementFollowing } from "./delete.js";
|
||||
import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
||||
import { LocalFollowingsCache } from "@/misc/cache.js";
|
||||
|
||||
type Local =
|
||||
| ILocalUser
|
||||
|
@ -91,6 +92,10 @@ async function removeFollow(followee: Both, follower: Both) {
|
|||
if (!following) return;
|
||||
|
||||
await Followings.delete(following.id);
|
||||
if (Users.isLocalUser(follower)) {
|
||||
const cache = await LocalFollowingsCache.init(follower.id);
|
||||
await cache.unfollow(followee.id);
|
||||
}
|
||||
decrementFollowing(follower, followee);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue