avoid race conditions in meta / instance insert

This commit is contained in:
Hazelnoot 2025-05-25 08:44:45 -04:00
parent c0ead9cf11
commit 3e7ab07b3c
2 changed files with 37 additions and 41 deletions

View file

@ -5,15 +5,13 @@
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
import * as Redis from 'ioredis';
import { DataSource, QueryFailedError } from 'typeorm';
import type { InstancesRepository } from '@/models/_.js';
import { MiInstance } from '@/models/Instance.js';
import type { MiInstance } from '@/models/Instance.js';
import { MemoryKVCache, RedisKVCache } from '@/misc/cache.js';
import { IdService } from '@/core/IdService.js';
import { DI } from '@/di-symbols.js';
import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js';
import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js';
@Injectable()
export class FederatedInstanceService implements OnApplicationShutdown {
@ -26,9 +24,6 @@ export class FederatedInstanceService implements OnApplicationShutdown {
@Inject(DI.instancesRepository)
private instancesRepository: InstancesRepository,
@Inject(DI.db)
private readonly db: DataSource,
private utilityService: UtilityService,
private idService: IdService,
) {
@ -58,11 +53,11 @@ export class FederatedInstanceService implements OnApplicationShutdown {
const cached = await this.federatedInstanceCache.get(host);
if (cached) return cached;
return await this.db.transaction(async tem => {
let index = await tem.findOneBy(MiInstance, { host });
if (index == null) {
await tem.insert(MiInstance, {
let index = await this.instancesRepository.findOneBy({ host });
if (index == null) {
await this.instancesRepository.createQueryBuilder('instance')
.insert()
.values({
id: this.idService.gen(),
host,
firstRetrievedAt: new Date(),
@ -71,14 +66,15 @@ export class FederatedInstanceService implements OnApplicationShutdown {
isMediaSilenced: this.utilityService.isMediaSilencedHost(host),
isAllowListed: this.utilityService.isAllowListedHost(host),
isBubbled: this.utilityService.isBubbledHost(host),
});
})
.orIgnore()
.execute();
index = await tem.findOneByOrFail(MiInstance, { host });
}
index = await this.instancesRepository.findOneByOrFail({ host });
}
await this.federatedInstanceCache.set(host, index);
return index;
});
await this.federatedInstanceCache.set(host, index);
return index;
}
@bindThis