Skip to content

Commit

Permalink
Optimizing for Cloudflare Caching
Browse files Browse the repository at this point in the history
  • Loading branch information
tar-bin committed Dec 20, 2024
1 parent 08a53cd commit e21c5b0
Show file tree
Hide file tree
Showing 14 changed files with 123 additions and 34 deletions.
7 changes: 4 additions & 3 deletions packages/backend/src/server/api/ApiCallService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export class ApiCallService implements OnApplicationShutdown {
return;
}
this.authenticateService.authenticate(token).then(([user, app]) => {
this.call(endpoint, user, app, body, null, request).then((res) => {
this.call(endpoint, user, app, body, null, request, reply).then((res) => {
if (request.method === 'GET' && endpoint.meta.cacheSec && !token && !user) {
reply.header('Cache-Control', `public, max-age=${endpoint.meta.cacheSec}`);
}
Expand Down Expand Up @@ -168,7 +168,7 @@ export class ApiCallService implements OnApplicationShutdown {
this.call(endpoint, user, app, fields, {
name: multipartData.filename,
path: path,
}, request).then((res) => {
}, request, reply).then((res) => {
this.send(reply, res);
}).catch((err: ApiError) => {
this.#sendApiError(reply, err);
Expand Down Expand Up @@ -239,6 +239,7 @@ export class ApiCallService implements OnApplicationShutdown {
path: string;
} | null,
request: FastifyRequest<{ Body: Record<string, unknown> | undefined, Querystring: Record<string, unknown> }>,
reply: FastifyReply,
) {
const isSecure = user != null && token == null;

Expand Down Expand Up @@ -372,7 +373,7 @@ export class ApiCallService implements OnApplicationShutdown {
}

// API invoking
return await ep.exec(data, user, token, file, request.ip, request.headers).catch((err: Error) => {
return await ep.exec(data, user, token, reply, file, request.ip, request.headers).catch((err: Error) => {
if (err instanceof ApiError || err instanceof AuthenticationError) {
throw err;
} else if (err instanceof IdentifiableError) {
Expand Down
9 changes: 5 additions & 4 deletions packages/backend/src/server/api/endpoint-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { MiLocalUser } from '@/models/User.js';
import type { MiAccessToken } from '@/models/AccessToken.js';
import { ApiError } from './error.js';
import type { IEndpointMeta } from './endpoints.js';
import type { FastifyReply } from 'fastify';

const Ajv = _Ajv.default;

Expand Down Expand Up @@ -39,16 +40,16 @@ type File = {

// TODO: paramsの型をT['params']のスキーマ定義から推論する
type Executor<T extends IEndpointMeta, Ps extends Schema> =
(params: SchemaType<Ps>, user: T['requireCredential'] extends true ? MiLocalUser : MiLocalUser | null, token: MiAccessToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record<string, string> | null) =>
(params: SchemaType<Ps>, user: T['requireCredential'] extends true ? MiLocalUser : MiLocalUser | null, token: MiAccessToken | null, reply: FastifyReply, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record<string, string> | null) =>
Promise<T['res'] extends undefined ? Response : SchemaType<NonNullable<T['res']>>>;

export abstract class Endpoint<T extends IEndpointMeta, Ps extends Schema> {
public exec: (params: any, user: T['requireCredential'] extends true ? MiLocalUser : MiLocalUser | null, token: MiAccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => Promise<any>;
public exec: (params: any, user: T['requireCredential'] extends true ? MiLocalUser : MiLocalUser | null, token: MiAccessToken | null, reply: FastifyReply, file?: File, ip?: string | null, headers?: Record<string, string> | null) => Promise<any>;

constructor(meta: T, paramDef: Ps, cb: Executor<T, Ps>) {
const validate = ajv.compile(paramDef);

this.exec = (params: any, user: T['requireCredential'] extends true ? MiLocalUser : MiLocalUser | null, token: MiAccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => {
this.exec = (params: any, user: T['requireCredential'] extends true ? MiLocalUser : MiLocalUser | null, token: MiAccessToken | null, reply: FastifyReply, file?: File, ip?: string | null, headers?: Record<string, string> | null) => {
let cleanup: undefined | (() => void) = undefined;

if (meta.requireFile) {
Expand Down Expand Up @@ -79,7 +80,7 @@ export abstract class Endpoint<T extends IEndpointMeta, Ps extends Schema> {
return Promise.reject(err);
}

return cb(params as SchemaType<Ps>, user, token, file, cleanup, ip, headers);
return cb(params as SchemaType<Ps>, user, token, reply, file, cleanup, ip, headers);
};
}
}
9 changes: 8 additions & 1 deletion packages/backend/src/server/api/endpoints/notes/show.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const meta = {
tags: ['notes'],

requireCredential: false,
allowGet: true,

res: {
type: 'object',
Expand Down Expand Up @@ -43,12 +44,18 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private noteEntityService: NoteEntityService,
private getterService: GetterService,
) {
super(meta, paramDef, async (ps, me) => {
super(meta, paramDef, async (ps, me, token, reply) => {
const note = await this.getterService.getNote(ps.noteId).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
throw err;
});

if (["followers", "specified"].includes(note.visibility)) {
reply.header('Cache-Control', 'private, max-age=600');
} else {
reply.header('Cache-Control', 'public');
}

return await this.noteEntityService.pack(note, me, {
detail: true,
});
Expand Down
12 changes: 9 additions & 3 deletions packages/backend/src/server/api/stream/channels/antenna.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class AntennaChannel extends Channel {
public static readonly requireCredential = true as const;
public static readonly kind = 'read:account';
private antennaId: string;
private idOnly: boolean;

constructor(
private noteEntityService: NoteEntityService,
Expand All @@ -29,6 +30,7 @@ class AntennaChannel extends Channel {
@bindThis
public async init(params: any) {
this.antennaId = params.antennaId as string;
this.idOnly = params.idOnly ?? false;

// Subscribe stream
this.subscriber.on(`antennaStream:${this.antennaId}`, this.onEvent);
Expand All @@ -49,9 +51,13 @@ class AntennaChannel extends Channel {

if (this.isNoteMutedOrBlocked(note)) return;

this.connection.cacheNote(note);

this.send('note', note);
if (this.idOnly && !["followers", "specified"].includes(note.visibility)) {
const idOnlyNote = { id: note.id, idOnly: true };
this.send("note", idOnlyNote);
} else {
this.connection.cacheNote(note);
this.send("note", note);
}
} else {
this.send(data.type, data.body);
}
Expand Down
12 changes: 9 additions & 3 deletions packages/backend/src/server/api/stream/channels/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class ChannelChannel extends Channel {
public static readonly shouldShare = false;
public static readonly requireCredential = false as const;
private channelId: string;
private idOnly: boolean;

constructor(
private noteEntityService: NoteEntityService,
Expand All @@ -29,6 +30,7 @@ class ChannelChannel extends Channel {
@bindThis
public async init(params: any) {
this.channelId = params.channelId as string;
this.idOnly = params.idOnly ?? false;

// Subscribe stream
this.subscriber.on('notesStream', this.onNote);
Expand All @@ -55,9 +57,13 @@ class ChannelChannel extends Channel {
}
}

this.connection.cacheNote(note);

this.send('note', note);
if (this.idOnly && !["followers", "specified"].includes(note.visibility)) {
const idOnlyNote = { id: note.id, idOnly: true };
this.send("note", idOnlyNote);
} else {
this.connection.cacheNote(note);
this.send("note", note);
}
}

@bindThis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class GlobalTimelineChannel extends Channel {
public static readonly requireCredential = false as const;
private withRenotes: boolean;
private withFiles: boolean;
private idOnly: boolean;

constructor(
private metaService: MetaService,
Expand All @@ -38,6 +39,7 @@ class GlobalTimelineChannel extends Channel {

this.withRenotes = params.withRenotes ?? true;
this.withFiles = params.withFiles ?? false;
this.idOnly = params.idOnly ?? false;

// Subscribe events
this.subscriber.on('notesStream', this.onNote);
Expand Down Expand Up @@ -85,9 +87,13 @@ class GlobalTimelineChannel extends Channel {
}
}

this.connection.cacheNote(note);

this.send('note', note);
if (this.idOnly && !["followers", "specified"].includes(note.visibility)) {
const idOnlyNote = { id: note.id, idOnly: true };
this.send("note", idOnlyNote);
} else {
this.connection.cacheNote(note);
this.send("note", note);
}
}

@bindThis
Expand Down
12 changes: 9 additions & 3 deletions packages/backend/src/server/api/stream/channels/home-timeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class HomeTimelineChannel extends Channel {
public static readonly kind = 'read:account';
private withRenotes: boolean;
private withFiles: boolean;
private idOnly: boolean;

constructor(
private noteEntityService: NoteEntityService,
Expand All @@ -32,6 +33,7 @@ class HomeTimelineChannel extends Channel {
public async init(params: any) {
this.withRenotes = params.withRenotes ?? true;
this.withFiles = params.withFiles ?? false;
this.idOnly = params.idOnly ?? false;

this.subscriber.on('notesStream', this.onNote);
}
Expand Down Expand Up @@ -89,9 +91,13 @@ class HomeTimelineChannel extends Channel {
}
}

this.connection.cacheNote(note);

this.send('note', note);
if (this.idOnly && !["followers", "specified"].includes(note.visibility)) {
const idOnlyNote = { id: note.id, idOnly: true };
this.send("note", idOnlyNote);
} else {
this.connection.cacheNote(note);
this.send("note", note);
}
}

@bindThis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class HybridTimelineChannel extends Channel {
private withRenotes: boolean;
private withReplies: boolean;
private withFiles: boolean;
private idOnly: boolean;

constructor(
private metaService: MetaService,
Expand All @@ -41,6 +42,7 @@ class HybridTimelineChannel extends Channel {
this.withRenotes = params.withRenotes ?? true;
this.withReplies = params.withReplies ?? false;
this.withFiles = params.withFiles ?? false;
this.idOnly = params.idOnly ?? false;

// Subscribe events
this.subscriber.on('notesStream', this.onNote);
Expand Down Expand Up @@ -103,9 +105,13 @@ class HybridTimelineChannel extends Channel {
}
}

this.connection.cacheNote(note);

this.send('note', note);
if (this.idOnly && !["followers", "specified"].includes(note.visibility)) {
const idOnlyNote = { id: note.id, idOnly: true };
this.send("note", idOnlyNote);
} else {
this.connection.cacheNote(note);
this.send("note", note);
}
}

@bindThis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class LocalTimelineChannel extends Channel {
private withRenotes: boolean;
private withReplies: boolean;
private withFiles: boolean;
private idOnly: boolean;

constructor(
private metaService: MetaService,
Expand All @@ -40,6 +41,7 @@ class LocalTimelineChannel extends Channel {
this.withRenotes = params.withRenotes ?? true;
this.withReplies = params.withReplies ?? false;
this.withFiles = params.withFiles ?? false;
this.idOnly = params.idOnly ?? false;

// Subscribe events
this.subscriber.on('notesStream', this.onNote);
Expand Down Expand Up @@ -88,9 +90,13 @@ class LocalTimelineChannel extends Channel {
}
}

this.connection.cacheNote(note);

this.send('note', note);
if (this.idOnly && !["followers", "specified"].includes(note.visibility)) {
const idOnlyNote = { id: note.id, idOnly: true };
this.send("note", idOnlyNote);
} else {
this.connection.cacheNote(note);
this.send("note", note);
}
}

@bindThis
Expand Down
12 changes: 9 additions & 3 deletions packages/backend/src/server/api/stream/channels/role-timeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class RoleTimelineChannel extends Channel {
public static readonly shouldShare = false;
public static readonly requireCredential = false as const;
private roleId: string;
private idOnly: boolean;

constructor(
private noteEntityService: NoteEntityService,
Expand All @@ -31,6 +32,7 @@ class RoleTimelineChannel extends Channel {
@bindThis
public async init(params: any) {
this.roleId = params.roleId as string;
this.idOnly = params.idOnly ?? false;

this.subscriber.on(`roleTimelineStream:${this.roleId}`, this.onEvent);
}
Expand Down Expand Up @@ -71,9 +73,13 @@ class RoleTimelineChannel extends Channel {
}
}

this.connection.cacheNote(note);

this.send('note', note);
if (this.idOnly && !["followers", "specified"].includes(note.visibility)) {
const idOnlyNote = { id: note.id, idOnly: true };
this.send("note", idOnlyNote);
} else {
this.connection.cacheNote(note);
this.send("note", note);
}
} else {
this.send(data.type, data.body);
}
Expand Down
12 changes: 9 additions & 3 deletions packages/backend/src/server/api/stream/channels/user-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class UserListChannel extends Channel {
private listUsersClock: NodeJS.Timeout;
private withFiles: boolean;
private withRenotes: boolean;
private idOnly: boolean;

constructor(
private userListsRepository: UserListsRepository,
Expand All @@ -40,6 +41,7 @@ class UserListChannel extends Channel {
this.listId = params.listId as string;
this.withFiles = params.withFiles ?? false;
this.withRenotes = params.withRenotes ?? true;
this.idOnly = params.idOnly ?? false;

// Check existence and owner
const listExist = await this.userListsRepository.exists({
Expand Down Expand Up @@ -128,9 +130,13 @@ class UserListChannel extends Channel {
}
}

this.connection.cacheNote(note);

this.send('note', note);
if (this.idOnly && !["followers", "specified"].includes(note.visibility)) {
const idOnlyNote = { id: note.id, idOnly: true };
this.send("note", idOnlyNote);
} else {
this.connection.cacheNote(note);
this.send("note", note);
}
}

@bindThis
Expand Down
Loading

0 comments on commit e21c5b0

Please sign in to comment.