Skip to content

Commit 5138672

Browse files
authored
perf(backend): Defer instance metadata update (#727)
1 parent 8692712 commit 5138672

File tree

3 files changed

+56
-5
lines changed

3 files changed

+56
-5
lines changed

packages/backend/src/core/NoteCreateService.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import { isReply } from '@/misc/is-reply.js';
5959
import { trackPromise } from '@/misc/promise-tracker.js';
6060
import { isNotNull } from '@/misc/is-not-null.js';
6161
import { IdentifiableError } from '@/misc/identifiable-error.js';
62+
import { CollapsedQueue } from '@/misc/collapsed-queue.js';
6263

6364
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
6465

@@ -150,6 +151,7 @@ type Option = {
150151
export class NoteCreateService implements OnApplicationShutdown {
151152
private logger: Logger;
152153
#shutdownController = new AbortController();
154+
private updateNotesCountQueue: CollapsedQueue<MiNote['id'], number>;
153155

154156
constructor(
155157
@Inject(DI.config)
@@ -217,6 +219,7 @@ export class NoteCreateService implements OnApplicationShutdown {
217219
private loggerService: LoggerService,
218220
) {
219221
this.logger = this.loggerService.getLogger('note:create');
222+
this.updateNotesCountQueue = new CollapsedQueue(60 * 1000 * 5, this.collapseNotesCount, this.performUpdateNotesCount);
220223
}
221224

222225
@bindThis
@@ -548,7 +551,7 @@ export class NoteCreateService implements OnApplicationShutdown {
548551
// Register host
549552
if (this.userEntityService.isRemoteUser(user)) {
550553
this.federatedInstanceService.fetch(user.host).then(async i => {
551-
this.instancesRepository.increment({ id: i.id }, 'notesCount', 1);
554+
this.updateNotesCountQueue.enqueue(i.id, 1);
552555
if ((await this.metaService.fetch()).enableChartsForFederatedInstances) {
553556
this.instanceChart.updateNote(i.host, note, true);
554557
}
@@ -1092,6 +1095,16 @@ export class NoteCreateService implements OnApplicationShutdown {
10921095
);
10931096
}
10941097

1098+
@bindThis
1099+
private collapseNotesCount(oldValue: number, newValue: number) {
1100+
return oldValue + newValue;
1101+
}
1102+
1103+
@bindThis
1104+
private performUpdateNotesCount(id: MiNote['id'], incrBy: number) {
1105+
this.instancesRepository.increment({ id: id }, 'notesCount', incrBy);
1106+
}
1107+
10951108
@bindThis
10961109
public dispose(): void {
10971110
this.#shutdownController.abort();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export class CollapsedQueue<K, V> {
2+
private jobs: Map<K, V> = new Map();
3+
4+
constructor(
5+
private timeout: number,
6+
private collapse: (oldValue: V, newValue: V) => V,
7+
private doJob: (key: K, value: V) => void,
8+
) { }
9+
10+
enqueue(key: K, value: V) {
11+
if (this.jobs.has(key)) {
12+
const old = this.jobs.get(key)!;
13+
const merged = this.collapse(old, value);
14+
this.jobs.set(key, merged);
15+
} else {
16+
this.jobs.set(key, value);
17+
setTimeout(() => {
18+
const value = this.jobs.get(key)!;
19+
this.jobs.delete(key);
20+
this.doJob(key, value);
21+
}, this.timeout);
22+
}
23+
}
24+
}

packages/backend/src/queue/processors/InboxProcessorService.ts

+18-4
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@ import { bindThis } from '@/decorators.js';
2828
import { IdentifiableError } from '@/misc/identifiable-error.js';
2929
import { QueueLoggerService } from '../QueueLoggerService.js';
3030
import type { InboxJobData } from '../types.js';
31+
import { CollapsedQueue } from '@/misc/collapsed-queue.js';
32+
import { MiNote } from '@/models/Note.js';
3133

3234
@Injectable()
3335
export class InboxProcessorService {
3436
private logger: Logger;
37+
private updateInstanceQueue: CollapsedQueue<MiNote['id'], Date>;
3538

3639
constructor(
3740
private utilityService: UtilityService,
@@ -48,6 +51,7 @@ export class InboxProcessorService {
4851
private queueLoggerService: QueueLoggerService,
4952
) {
5053
this.logger = this.queueLoggerService.logger.createSubLogger('inbox');
54+
this.updateInstanceQueue = new CollapsedQueue(60 * 1000 * 5, this.collapseUpdateInstanceJobs, this.performUpdateInstance);
5155
}
5256

5357
@bindThis
@@ -180,10 +184,7 @@ export class InboxProcessorService {
180184

181185
// Update stats
182186
this.federatedInstanceService.fetch(authUser.user.host).then(i => {
183-
this.federatedInstanceService.update(i.id, {
184-
latestRequestReceivedAt: new Date(),
185-
isNotResponding: false,
186-
});
187+
this.updateInstanceQueue.enqueue(i.id, new Date());
187188

188189
this.fetchInstanceMetadataService.fetchInstanceMetadata(i);
189190

@@ -211,4 +212,17 @@ export class InboxProcessorService {
211212
}
212213
return 'ok';
213214
}
215+
216+
@bindThis
217+
public collapseUpdateInstanceJobs(oldValue: Date, newValue: Date) {
218+
return oldValue < newValue ? newValue : oldValue;
219+
}
220+
221+
@bindThis
222+
public performUpdateInstance(id: string, value: Date) {
223+
this.federatedInstanceService.update(id, {
224+
latestRequestReceivedAt: value,
225+
isNotResponding: false,
226+
});
227+
}
214228
}

0 commit comments

Comments
 (0)