summaryrefslogtreecommitdiff
path: root/packages/backend/src/core
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2024-10-12 10:43:28 +0100
committerdakkar <dakkar@thenautilus.net>2024-10-12 10:57:57 +0100
commit06bd29f2093cee6c1c0efd02e08c17088415e3ef (patch)
tree9a4acd0c53c640557dac52dfaa847fe2b871c3e5 /packages/backend/src/core
parentmerge: New logo (!681) (diff)
downloadsharkey-06bd29f2093cee6c1c0efd02e08c17088415e3ef.tar.gz
sharkey-06bd29f2093cee6c1c0efd02e08c17088415e3ef.tar.bz2
sharkey-06bd29f2093cee6c1c0efd02e08c17088415e3ef.zip
try to avoid `insert` races in `FederatedInstanceService`
Despite the cache, different processes can race to insert a row for the same remote host. This is particularly apparent in our unit tests, with `test/unit/activitypub.ts` randomly failing. This is a (somewhat clumsy) attempt at working around that race: trap the "duplicate key value" error, and fetch the record. Tests pass, with or without values in the cache.
Diffstat (limited to 'packages/backend/src/core')
-rw-r--r--packages/backend/src/core/FederatedInstanceService.ts25
1 files changed, 20 insertions, 5 deletions
diff --git a/packages/backend/src/core/FederatedInstanceService.ts b/packages/backend/src/core/FederatedInstanceService.ts
index 7aeeb78178..7ec565557c 100644
--- a/packages/backend/src/core/FederatedInstanceService.ts
+++ b/packages/backend/src/core/FederatedInstanceService.ts
@@ -12,6 +12,8 @@ import { IdService } from '@/core/IdService.js';
import { DI } from '@/di-symbols.js';
import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js';
+import { QueryFailedError } from 'typeorm';
+import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js';
@Injectable()
export class FederatedInstanceService implements OnApplicationShutdown {
@@ -56,11 +58,24 @@ export class FederatedInstanceService implements OnApplicationShutdown {
const index = await this.instancesRepository.findOneBy({ host });
if (index == null) {
- const i = await this.instancesRepository.insertOne({
- id: this.idService.gen(),
- host,
- firstRetrievedAt: new Date(),
- });
+ let i;
+ try {
+ i = await this.instancesRepository.insertOne({
+ id: this.idService.gen(),
+ host,
+ firstRetrievedAt: new Date(),
+ });
+ } catch (e: unknown) {
+ if (e instanceof QueryFailedError) {
+ if (isDuplicateKeyValueError(e)) {
+ i = await this.instancesRepository.findOneBy({ host });
+ }
+ }
+
+ if (i == null) {
+ throw e;
+ }
+ }
this.federatedInstanceCache.set(host, i);
return i;