From 58dfd45ce101b48d0c9c73c47be0864d29a93e3c Mon Sep 17 00:00:00 2001 From: Johann150 Date: Wed, 9 Nov 2022 18:47:28 +0100 Subject: [PATCH] server: reduce dead instance detection to 7 days --- CALCKEY.md | 1 + .../backend/src/misc/skipped-instances.ts | 54 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 packages/backend/src/misc/skipped-instances.ts diff --git a/CALCKEY.md b/CALCKEY.md index 990908ca8..8f64109e7 100644 --- a/CALCKEY.md +++ b/CALCKEY.md @@ -124,3 +124,4 @@ - 384e8c49b738f576ba8843296de6cebf01c1b247: server: allow to like own gallery posts - 4c5aa9e53887cca5561fcec6ab0754e018f589a5: server: allow to like own pages - 923c93da1228458dd65be47483c198a1a9191bcf: use await for notes.countBy + - ca90cedba0a0704b503c2778694230f5a7dfbace: server: reduce dead instance detection to 7 days diff --git a/packages/backend/src/misc/skipped-instances.ts b/packages/backend/src/misc/skipped-instances.ts new file mode 100644 index 000000000..36367b2e5 --- /dev/null +++ b/packages/backend/src/misc/skipped-instances.ts @@ -0,0 +1,54 @@ +import { Brackets } from 'typeorm'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Instances } from '@/models/index.js'; +import { Instance } from '@/models/entities/instance.js'; +import { DAY } from '@/const.js'; + +// Threshold from last contact after which an instance will be considered +// "dead" and should no longer get activities delivered to it. +const deadThreshold = 7 * DAY; + +/** + * Returns the subset of hosts which should be skipped. + * + * @param hosts array of punycoded instance hosts + * @returns array of punycoed instance hosts that should be skipped (subset of hosts parameter) + */ +export async function skippedInstances(hosts: Array): Array { + // first check for blocked instances since that info may already be in memory + const { blockedHosts } = await fetchMeta(); + + const skipped = hosts.filter(host => blockedHosts.includes(host)); + // if possible return early and skip accessing the database + if (skipped.length === hosts.length) return hosts; + + const deadTime = new Date(Date.now() - deadThreshold); + + return skipped.concat( + await Instances.createQueryBuilder('instance') + .where('instance.host in (:...hosts)', { + // don't check hosts again that we already know are suspended + // also avoids adding duplicates to the list + hosts: hosts.filter(host => !skipped.includes(host)), + }) + .andWhere(new Brackets(qb => { qb + .where('instance.isSuspended') + .orWhere('instance.lastCommunicatedAt < :deadTime', { deadTime }); + })) + .select('host') + .getRawMany() + ); +} + +/** + * Returns whether a specific host (punycoded) should be skipped. + * Convenience wrapper around skippedInstances which should only be used if there is a single host to check. + * If you have multiple hosts, consider using skippedInstances instead to do a bulk check. + * + * @param host punycoded instance host + * @returns whether the given host should be skipped + */ +export async function shouldSkipInstance(host: Instance['host']): boolean { + const skipped = await skippedInstances([host]); + return skipped.length > 0; +}