merge: cache URL previews on the server (!565)

View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/565

Approved-by: fEmber <acomputerdog@gmail.com>
Approved-by: Luna <her@mint.lgbt>
This commit is contained in:
dakkar 2024-07-05 10:43:39 +00:00
commit c4f4041cf8

View file

@ -17,20 +17,33 @@ import { bindThis } from '@/decorators.js';
import { ApiError } from '@/server/api/error.js'; import { ApiError } from '@/server/api/error.js';
import { MiMeta } from '@/models/Meta.js'; import { MiMeta } from '@/models/Meta.js';
import type { FastifyRequest, FastifyReply } from 'fastify'; import type { FastifyRequest, FastifyReply } from 'fastify';
import * as Redis from 'ioredis';
import { RedisKVCache } from '@/misc/cache.js';
@Injectable() @Injectable()
export class UrlPreviewService { export class UrlPreviewService {
private logger: Logger; private logger: Logger;
private previewCache: RedisKVCache<SummalyResult>;
constructor( constructor(
@Inject(DI.config) @Inject(DI.config)
private config: Config, private config: Config,
@Inject(DI.redis)
private redisClient: Redis.Redis,
private metaService: MetaService, private metaService: MetaService,
private httpRequestService: HttpRequestService, private httpRequestService: HttpRequestService,
private loggerService: LoggerService, private loggerService: LoggerService,
) { ) {
this.logger = this.loggerService.getLogger('url-preview'); this.logger = this.loggerService.getLogger('url-preview');
this.previewCache = new RedisKVCache<SummalyResult>(this.redisClient, 'summaly', {
lifetime: 1000 * 86400,
memoryCacheLifetime: 1000 * 10 * 60,
fetcher: (key: string) => { throw new Error('the UrlPreview cache should never fetch'); },
toRedisConverter: (value) => JSON.stringify(value),
fromRedisConverter: (value) => JSON.parse(value),
});
} }
@bindThis @bindThis
@ -75,9 +88,19 @@ export class UrlPreviewService {
}; };
} }
const key = `${url}@${lang}`;
const cached = await this.previewCache.get(key);
if (cached !== undefined) {
this.logger.info(`Returning cache preview of ${key}`);
// Cache 7days
reply.header('Cache-Control', 'max-age=604800, immutable');
return cached;
}
this.logger.info(meta.urlPreviewSummaryProxyUrl this.logger.info(meta.urlPreviewSummaryProxyUrl
? `(Proxy) Getting preview of ${url}@${lang} ...` ? `(Proxy) Getting preview of ${key} ...`
: `Getting preview of ${url}@${lang} ...`); : `Getting preview of ${key} ...`);
try { try {
const summary = meta.urlPreviewSummaryProxyUrl const summary = meta.urlPreviewSummaryProxyUrl
@ -97,6 +120,8 @@ export class UrlPreviewService {
summary.icon = this.wrap(summary.icon); summary.icon = this.wrap(summary.icon);
summary.thumbnail = this.wrap(summary.thumbnail); summary.thumbnail = this.wrap(summary.thumbnail);
this.previewCache.set(key, summary);
// Cache 7days // Cache 7days
reply.header('Cache-Control', 'max-age=604800, immutable'); reply.header('Cache-Control', 'max-age=604800, immutable');