summaryrefslogtreecommitdiff
path: root/packages/backend/src/core
diff options
context:
space:
mode:
authorHazelnoot <acomputerdog@gmail.com>2025-05-24 18:29:10 -0400
committerHazelnoot <acomputerdog@gmail.com>2025-05-28 21:31:40 -0400
commit305250d0738b1fc7332ee9556b8d9e6aed5a8237 (patch)
tree06a5893400bcb32683b6d49c15609464502270cf /packages/backend/src/core
parentadd diff-arrays utility for efficient array diffs (diff)
downloadsharkey-305250d0738b1fc7332ee9556b8d9e6aed5a8237.tar.gz
sharkey-305250d0738b1fc7332ee9556b8d9e6aed5a8237.tar.bz2
sharkey-305250d0738b1fc7332ee9556b8d9e6aed5a8237.zip
persist changes to meta host lists to instance table
Diffstat (limited to 'packages/backend/src/core')
-rw-r--r--packages/backend/src/core/MetaService.ts55
1 files changed, 53 insertions, 2 deletions
diff --git a/packages/backend/src/core/MetaService.ts b/packages/backend/src/core/MetaService.ts
index 40e7439f5f..16be22ac19 100644
--- a/packages/backend/src/core/MetaService.ts
+++ b/packages/backend/src/core/MetaService.ts
@@ -4,7 +4,7 @@
*/
import { Inject, Injectable } from '@nestjs/common';
-import { DataSource } from 'typeorm';
+import { DataSource, EntityManager } from 'typeorm';
import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js';
import { MiMeta } from '@/models/Meta.js';
@@ -12,6 +12,8 @@ import { GlobalEventService } from '@/core/GlobalEventService.js';
import { bindThis } from '@/decorators.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js';
import { FeaturedService } from '@/core/FeaturedService.js';
+import { MiInstance } from '@/models/Instance.js';
+import { diffArrays } from '@/misc/diff-arrays.js';
import type { OnApplicationShutdown } from '@nestjs/common';
@Injectable()
@@ -103,7 +105,7 @@ export class MetaService implements OnApplicationShutdown {
let before: MiMeta | undefined;
const updated = await this.db.transaction(async transactionalEntityManager => {
- const metas = await transactionalEntityManager.find(MiMeta, {
+ const metas: (MiMeta | undefined)[] = await transactionalEntityManager.find(MiMeta, {
order: {
id: 'DESC',
},
@@ -126,6 +128,10 @@ export class MetaService implements OnApplicationShutdown {
},
});
+ // Propagate changes to blockedHosts, silencedHosts, mediaSilencedHosts, federationInstances, and bubbleInstances to the relevant instance rows
+ // Do this inside the transaction to avoid potential race condition (when an instance gets registered while we're updating).
+ await this.persistBlocks(transactionalEntityManager, before ?? {}, afters[0]);
+
return afters[0];
});
@@ -159,4 +165,49 @@ export class MetaService implements OnApplicationShutdown {
public onApplicationShutdown(signal?: string | undefined): void {
this.dispose();
}
+
+ private async persistBlocks(tem: EntityManager, before: Partial<MiMeta>, after: Partial<MiMeta>): Promise<void> {
+ await this.persistBlock(tem, before.blockedHosts, after.blockedHosts, 'isBlocked');
+ await this.persistBlock(tem, before.silencedHosts, after.silencedHosts, 'isSilenced');
+ await this.persistBlock(tem, before.mediaSilencedHosts, after.mediaSilencedHosts, 'isMediaSilenced');
+ await this.persistBlock(tem, before.federationHosts, after.federationHosts, 'isAllowListed');
+ await this.persistBlock(tem, before.bubbleInstances, after.bubbleInstances, 'isBubbled');
+ }
+
+ private async persistBlock(tem: EntityManager, before: string[] | undefined, after: string[] | undefined, field: keyof MiInstance): Promise<void> {
+ const { added, removed } = diffArrays(before, after);
+
+ if (removed.length > 0) {
+ await this.updateInstancesByHost(tem, field, false, removed);
+ }
+
+ if (added.length > 0) {
+ await this.updateInstancesByHost(tem, field, true, added);
+ }
+ }
+
+ private async updateInstancesByHost(tem: EntityManager, field: keyof MiInstance, value: boolean, hosts: string[]): Promise<void> {
+ // Use non-array queries when possible, as they are indexed and can be much faster.
+ if (hosts.length === 1) {
+ const pattern = genHostPattern(hosts[0]);
+ await tem
+ .createQueryBuilder(MiInstance, 'instance')
+ .update()
+ .set({ [field]: value })
+ .where('(lower(reverse("host")) || \'.\') LIKE :pattern', { pattern })
+ .execute();
+ } else if (hosts.length > 1) {
+ const patterns = hosts.map(host => genHostPattern(host));
+ await tem
+ .createQueryBuilder(MiInstance, 'instance')
+ .update()
+ .set({ [field]: value })
+ .where('(lower(reverse("host")) || \'.\') LIKE ANY (:patterns)', {patterns})
+ .execute();
+ }
+ }
+}
+
+function genHostPattern(host: string): string {
+ return host.toLowerCase().split('').reverse().join('') + '.%';
}