-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Visibility timeout heartbeat #124
Changes from all commits
07f2664
7cbb584
e1bca76
39aa502
86ec38c
89c6935
05b5b94
762815a
634464f
2a89a4a
fa66512
df9eea1
db8613b
9b3c7e1
f8842d7
23bad81
675f7ab
56b486b
b752d9f
712f18d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,15 @@ | ||
import { setTimeout } from 'node:timers/promises' | ||
|
||
import type { SNSClient } from '@aws-sdk/client-sns' | ||
import type { SQSClient } from '@aws-sdk/client-sqs' | ||
import { waitAndRetry } from '@lokalise/node-core' | ||
import { assertQueue, deleteQueue, getQueueAttributes } from '@message-queue-toolkit/sqs' | ||
import type { AwilixContainer } from 'awilix' | ||
import { asValue } from 'awilix' | ||
import { describe, beforeEach, afterEach, expect, it, beforeAll } from 'vitest' | ||
|
||
import { assertTopic, deleteTopic } from '../../lib/utils/snsUtils' | ||
import type { SnsPermissionPublisher } from '../publishers/SnsPermissionPublisher' | ||
import { SnsPermissionPublisher } from '../publishers/SnsPermissionPublisher' | ||
import { registerDependencies } from '../utils/testContext' | ||
import type { Dependencies } from '../utils/testContext' | ||
|
||
|
@@ -88,6 +92,7 @@ describe('SnsSqsPermissionConsumer', () => { | |
QueueName: 'existingQueue', | ||
Attributes: { | ||
KmsMasterKeyId: 'othervalue', | ||
VisibilityTimeout: '10', | ||
}, | ||
}, | ||
updateAttributesIfExists: true, | ||
|
@@ -106,7 +111,10 @@ describe('SnsSqsPermissionConsumer', () => { | |
queueUrl: newConsumer.subscriptionProps.queueUrl, | ||
}) | ||
|
||
expect(attributes.result?.attributes!.KmsMasterKeyId).toBe('othervalue') | ||
expect(attributes.result?.attributes).toMatchObject({ | ||
KmsMasterKeyId: 'othervalue', | ||
VisibilityTimeout: '10', | ||
}) | ||
}) | ||
|
||
it('updates existing queue when one with different attributes exist and sets the policy', async () => { | ||
|
@@ -435,4 +443,70 @@ describe('SnsSqsPermissionConsumer', () => { | |
}) | ||
}) | ||
}) | ||
|
||
describe('visibility timeout', () => { | ||
const topicName = 'myTestTopic' | ||
const queueName = 'myTestQueue' | ||
let diContainer: AwilixContainer<Dependencies> | ||
|
||
beforeEach(async () => { | ||
diContainer = await registerDependencies({ | ||
permissionConsumer: asValue(() => undefined), | ||
permissionPublisher: asValue(() => undefined), | ||
}) | ||
}) | ||
|
||
afterEach(async () => { | ||
await diContainer.cradle.awilixManager.executeDispose() | ||
await diContainer.dispose() | ||
}) | ||
|
||
it.each([false, true])('using 2 consumers with heartbeat -> %s', async (heartbeatEnabled) => { | ||
let consumer1IsProcessing = false | ||
let consumer1Counter = 0 | ||
let consumer2Counter = 0 | ||
|
||
const consumer1 = new SnsSqsPermissionConsumer(diContainer.cradle, { | ||
creationConfig: { | ||
topic: { Name: topicName }, | ||
queue: { QueueName: queueName, Attributes: { VisibilityTimeout: '2' } }, | ||
}, | ||
consumerOverrides: { heartbeatInterval: heartbeatEnabled ? 1 : undefined }, | ||
removeHandlerOverride: async () => { | ||
consumer1IsProcessing = true | ||
await setTimeout(2800) // Wait to the visibility timeout to expire | ||
consumer1Counter++ | ||
consumer1IsProcessing = false | ||
return { result: 'success' } | ||
}, | ||
}) | ||
await consumer1.start() | ||
|
||
const consumer2 = new SnsSqsPermissionConsumer(diContainer.cradle, { | ||
locatorConfig: { | ||
queueUrl: consumer1.subscriptionProps.queueUrl, | ||
topicArn: consumer1.subscriptionProps.topicArn, | ||
subscriptionArn: consumer1.subscriptionProps.subscriptionArn, | ||
}, | ||
removeHandlerOverride: async () => { | ||
consumer2Counter++ | ||
return { result: 'success' } | ||
}, | ||
}) | ||
const publisher = new SnsPermissionPublisher(diContainer.cradle, { | ||
locatorConfig: { topicArn: consumer1.subscriptionProps.topicArn }, | ||
}) | ||
|
||
await publisher.publish({ id: '10', messageType: 'remove' }) | ||
// wait for consumer1 to start processing to start second consumer | ||
await waitAndRetry(() => consumer1IsProcessing, 5, 5) | ||
await consumer2.start() | ||
|
||
// wait for both consumers to process message | ||
await waitAndRetry(() => consumer1Counter > 0 && consumer2Counter > 0, 100, 40) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should assert that it resolves to true and not just timeouts There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The check is done using counters, in the second |
||
|
||
expect(consumer1Counter).toBe(1) | ||
expect(consumer2Counter).toBe(heartbeatEnabled ? 0 : 1) | ||
}) | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
before we release this version, let's also merge #121, so that we don't need to do semver majors in a row
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds great to me 🙇 I will wait to merge this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feel free to merge, just don't hurry releasing it :D.
After you are done, I will address any conflicts if there are on the other PR, and release both changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right, this repo doesn't have auto-release 😅 sorry, I was confused, thanks for the clarification 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merged, please let me know If can help with conflicts or release 🙇