From 513659bbc88496b8c1489780cc96d158a7f3cb9e Mon Sep 17 00:00:00 2001 From: Igor Savin Date: Fri, 23 Feb 2024 22:11:09 +0200 Subject: [PATCH] Avoid potential racing condition --- packages/sns/lib/sns/AbstractSnsService.ts | 15 ++++++++++++--- packages/sqs/lib/sqs/AbstractSqsService.ts | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/sns/lib/sns/AbstractSnsService.ts b/packages/sns/lib/sns/AbstractSnsService.ts index 70474e06..e0a76f3f 100644 --- a/packages/sns/lib/sns/AbstractSnsService.ts +++ b/packages/sns/lib/sns/AbstractSnsService.ts @@ -85,9 +85,13 @@ export abstract class AbstractSnsService< // @ts-ignore public topicArn: string + private isInitted: boolean + private initPromise?: Promise + constructor(dependencies: DependenciesType, options: SNSOptionsType) { super(dependencies, options) + this.isInitted = false this.snsClient = dependencies.snsClient } @@ -98,6 +102,7 @@ export abstract class AbstractSnsService< const initResult = await initSns(this.snsClient, this.locatorConfig, this.creationConfig) this.topicArn = initResult.topicArn + this.isInitted = true } // eslint-disable-next-line @typescript-eslint/require-await @@ -108,9 +113,13 @@ export abstract class AbstractSnsService< messageSchema: ZodSchema, options: SNSMessageOptions = {}, ): Promise { - if (this.topicArn === undefined) { - // Lazy loading - await this.init() + // If it's not initted yet, do the lazy init + if (!this.isInitted) { + // avoid multiple concurrent inits + if (!this.initPromise) { + this.initPromise = this.init() + } + await this.initPromise } try { diff --git a/packages/sqs/lib/sqs/AbstractSqsService.ts b/packages/sqs/lib/sqs/AbstractSqsService.ts index 5930956b..6decc18f 100644 --- a/packages/sqs/lib/sqs/AbstractSqsService.ts +++ b/packages/sqs/lib/sqs/AbstractSqsService.ts @@ -53,9 +53,13 @@ export abstract class AbstractSqsService< // @ts-ignore public queueArn: string + private isInitted: boolean + private initPromise?: Promise + constructor(dependencies: DependenciesType, options: SQSOptionsType) { super(dependencies, options) + this.isInitted = false this.sqsClient = dependencies.sqsClient } @@ -72,6 +76,7 @@ export abstract class AbstractSqsService< this.queueArn = queueArn this.queueUrl = queueUrl this.queueName = queueName + this.isInitted = true } protected async internalPublish( @@ -79,9 +84,13 @@ export abstract class AbstractSqsService< messageSchema: ZodSchema, options: SQSMessageOptions = {}, ): Promise { - if (!this.queueArn) { - // Lazy loading - await this.init() + // If it's not initted yet, do the lazy init + if (!this.isInitted) { + // avoid multiple concurrent inits + if (!this.initPromise) { + this.initPromise = this.init() + } + await this.initPromise } try {