Skip to content

Commit d24e84b

Browse files
committed
Cleanup
1 parent bbed226 commit d24e84b

3 files changed

Lines changed: 76 additions & 48 deletions

File tree

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ const consumer = new MySnsSqsConsumer(dependencies, {
286286
| `pollingIntervalMs` | `number` | `5000` | Interval between availability checks (ms) |
287287
| `timeoutMs` | `number \| NO_TIMEOUT` | - (required) | Maximum wait time before throwing `StartupResourcePollingTimeoutError`. Use `NO_TIMEOUT` to poll indefinitely |
288288
| `throwOnTimeout` | `boolean` | `true` | When `true`, throws error on timeout. When `false`, reports error via errorReporter, resets timeout counter, and continues polling |
289+
| `nonBlocking` | `boolean` | `false` | When `true`, `init()` returns immediately if resource is not available, and polling continues in the background. A callback is invoked when the resource becomes available |
289290

290291
### Environment-Specific Configuration
291292

@@ -338,6 +339,19 @@ import { NO_TIMEOUT } from '@message-queue-toolkit/core'
338339
}
339340
}
340341
}
342+
343+
// Non-blocking mode - service starts immediately, polling continues in background
344+
// Useful when you want the service to be available even if dependencies are not ready
345+
{
346+
locatorConfig: {
347+
queueUrl: '...',
348+
startupResourcePolling: {
349+
enabled: true,
350+
timeoutMs: 5 * 60 * 1000,
351+
nonBlocking: true, // init() resolves immediately
352+
}
353+
}
354+
}
341355
```
342356

343357
### Error Handling

packages/sns/lib/utils/snsInitter.ts

Lines changed: 61 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@ export async function initSnsSqs(
4747
creationConfig?: SNSCreationConfig & SQSCreationConfig,
4848
subscriptionConfig?: SNSSubscriptionOptions,
4949
extraParams?: InitSnsSqsExtraParams,
50-
): Promise<{ subscriptionArn: string; topicArn: string; queueUrl: string; queueName: string }> {
50+
): Promise<{
51+
subscriptionArn: string
52+
topicArn: string
53+
queueUrl: string
54+
queueName: string
55+
resourcesReady: boolean
56+
}> {
5157
if (!locatorConfig?.subscriptionArn) {
5258
if (!creationConfig?.topic && !locatorConfig?.topicArn && !locatorConfig?.topicName) {
5359
throw new Error(
@@ -303,61 +309,70 @@ export async function deleteSns(
303309
await deleteTopic(snsClient, stsClient, creationConfig.topic.Name)
304310
}
305311

306-
export async function initSns(
312+
async function initSnsWithLocator(
307313
snsClient: SNSClient,
308314
stsClient: STSClient,
309-
locatorConfig?: SNSTopicLocatorType,
310-
creationConfig?: SNSCreationConfig,
315+
locatorConfig: SNSTopicLocatorType,
311316
extraParams?: InitSnsExtraParams,
312317
) {
313-
if (locatorConfig) {
314-
if (!locatorConfig.topicArn && !locatorConfig.topicName) {
315-
throw new Error(
316-
'When locatorConfig for the topic is specified, either topicArn or topicName must be specified',
317-
)
318-
}
318+
if (!locatorConfig.topicArn && !locatorConfig.topicName) {
319+
throw new Error(
320+
'When locatorConfig for the topic is specified, either topicArn or topicName must be specified',
321+
)
322+
}
319323

320-
const topicArn =
321-
locatorConfig.topicArn ?? (await buildTopicArn(stsClient, locatorConfig.topicName ?? ''))
324+
const topicArn =
325+
locatorConfig.topicArn ?? (await buildTopicArn(stsClient, locatorConfig.topicName ?? ''))
322326

323-
const startupResourcePolling = locatorConfig.startupResourcePolling
327+
const startupResourcePolling = locatorConfig.startupResourcePolling
324328

325-
// If startup resource polling is enabled, poll for topic to become available
326-
if (isStartupResourcePollingEnabled(startupResourcePolling)) {
327-
const nonBlocking = startupResourcePolling.nonBlocking === true
329+
// If startup resource polling is enabled, poll for topic to become available
330+
if (isStartupResourcePollingEnabled(startupResourcePolling)) {
331+
const nonBlocking = startupResourcePolling.nonBlocking === true
328332

329-
const topicResult = await waitForResource({
330-
config: startupResourcePolling,
331-
resourceName: `SNS topic ${topicArn}`,
332-
logger: extraParams?.logger,
333-
errorReporter: extraParams?.errorReporter,
334-
onResourceAvailable: () => {
335-
if (nonBlocking) {
336-
extraParams?.onTopicReady?.({ topicArn })
337-
}
338-
},
339-
checkFn: async () => {
340-
const result = await getTopicAttributes(snsClient, topicArn)
341-
if (result.error === 'not_found') {
342-
return { isAvailable: false }
343-
}
344-
return { isAvailable: true, result: result.result }
345-
},
346-
})
347-
348-
// In non-blocking mode, return early if topic wasn't immediately available
349-
if (nonBlocking && topicResult === undefined) {
350-
return { topicArn, resourcesReady: false }
351-
}
352-
} else {
353-
// Original behavior: check once and fail immediately if not found
354-
const checkResult = await getTopicAttributes(snsClient, topicArn)
355-
if (checkResult.error === 'not_found') {
356-
throw new Error(`Topic with topicArn ${topicArn} does not exist.`)
357-
}
333+
const topicResult = await waitForResource({
334+
config: startupResourcePolling,
335+
resourceName: `SNS topic ${topicArn}`,
336+
logger: extraParams?.logger,
337+
errorReporter: extraParams?.errorReporter,
338+
onResourceAvailable: () => {
339+
if (nonBlocking) {
340+
extraParams?.onTopicReady?.({ topicArn })
341+
}
342+
},
343+
checkFn: async () => {
344+
const result = await getTopicAttributes(snsClient, topicArn)
345+
if (result.error === 'not_found') {
346+
return { isAvailable: false }
347+
}
348+
return { isAvailable: true, result: result.result }
349+
},
350+
})
351+
352+
// In non-blocking mode, return early if topic wasn't immediately available
353+
if (nonBlocking && topicResult === undefined) {
354+
return { topicArn, resourcesReady: false }
355+
}
356+
} else {
357+
// Original behavior: check once and fail immediately if not found
358+
const checkResult = await getTopicAttributes(snsClient, topicArn)
359+
if (checkResult.error === 'not_found') {
360+
throw new Error(`Topic with topicArn ${topicArn} does not exist.`)
358361
}
362+
}
363+
364+
return { topicArn, resourcesReady: true }
365+
}
359366

360-
return { topicArn, resourcesReady: true }
367+
export async function initSns(
368+
snsClient: SNSClient,
369+
stsClient: STSClient,
370+
locatorConfig?: SNSTopicLocatorType,
371+
creationConfig?: SNSCreationConfig,
372+
extraParams?: InitSnsExtraParams,
373+
) {
374+
if (locatorConfig) {
375+
return initSnsWithLocator(snsClient, stsClient, locatorConfig, extraParams)
361376
}
362377

363378
// create new topic if it does not exist

packages/sqs/lib/sqs/AbstractSqsService.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@ export abstract class AbstractSqsService<
9595
protected queueName: string
9696
// @ts-expect-error
9797
protected queueUrl: string
98-
// @ts-expect-error
99-
protected queueArn: string
98+
protected queueArn: string | undefined
10099
protected readonly isFifoQueue: boolean
101100

102101
constructor(dependencies: DependenciesType, options: SQSOptionsType) {

0 commit comments

Comments
 (0)