redis-smq 9.0.0-next.7 → 9.0.0-next.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/cjs/src/common/redis-client/scripts/lua/publish-message.lua +5 -4
- package/dist/cjs/src/common/redis-client/scripts/lua/publish-scheduled.lua +142 -107
- package/dist/cjs/src/common/redis-client/scripts/lua/requeue-delayed.lua +75 -37
- package/dist/cjs/src/common/redis-client/scripts/lua/requeue-immediate.lua +62 -29
- package/dist/cjs/src/common/redis-client/scripts/lua/requeue-message.lua +59 -41
- package/dist/cjs/src/common/redis-client/scripts/lua/shared-procedures/publish-message.lua +12 -1
- package/dist/cjs/src/consumer/message-handler/_/_delete-ephemeral-consumer-group.d.ts +4 -0
- package/dist/cjs/src/consumer/message-handler/_/_delete-ephemeral-consumer-group.d.ts.map +1 -0
- package/dist/cjs/src/consumer/message-handler/_/_delete-ephemeral-consumer-group.js +11 -0
- package/dist/cjs/src/consumer/message-handler/_/_delete-ephemeral-consumer-group.js.map +1 -0
- package/dist/cjs/src/consumer/message-handler/_/_generate-ephemeral-consumer-group-id.d.ts +2 -0
- package/dist/cjs/src/consumer/message-handler/_/_generate-ephemeral-consumer-group-id.d.ts.map +1 -0
- package/dist/cjs/src/consumer/message-handler/_/_generate-ephemeral-consumer-group-id.js +7 -0
- package/dist/cjs/src/consumer/message-handler/_/_generate-ephemeral-consumer-group-id.js.map +1 -0
- package/dist/cjs/src/consumer/message-handler/_/_prepare-consumer-group.d.ts +4 -0
- package/dist/cjs/src/consumer/message-handler/_/_prepare-consumer-group.d.ts.map +1 -0
- package/dist/cjs/src/consumer/message-handler/_/_prepare-consumer-group.js +44 -0
- package/dist/cjs/src/consumer/message-handler/_/_prepare-consumer-group.js.map +1 -0
- package/dist/cjs/src/consumer/message-handler/dequeue-message/dequeue-message.d.ts +1 -3
- package/dist/cjs/src/consumer/message-handler/dequeue-message/dequeue-message.d.ts.map +1 -1
- package/dist/cjs/src/consumer/message-handler/dequeue-message/dequeue-message.js +1 -41
- package/dist/cjs/src/consumer/message-handler/dequeue-message/dequeue-message.js.map +1 -1
- package/dist/cjs/src/consumer/message-handler/message-handler.d.ts +8 -6
- package/dist/cjs/src/consumer/message-handler/message-handler.d.ts.map +1 -1
- package/dist/cjs/src/consumer/message-handler/message-handler.js +80 -16
- package/dist/cjs/src/consumer/message-handler/message-handler.js.map +1 -1
- package/dist/cjs/src/consumer/message-handler/workers/publish-scheduled.worker.d.ts.map +1 -1
- package/dist/cjs/src/consumer/message-handler/workers/publish-scheduled.worker.js +7 -2
- package/dist/cjs/src/consumer/message-handler/workers/publish-scheduled.worker.js.map +1 -1
- package/dist/cjs/src/consumer/message-handler/workers/reap-consumers.worker.d.ts +1 -0
- package/dist/cjs/src/consumer/message-handler/workers/reap-consumers.worker.d.ts.map +1 -1
- package/dist/cjs/src/consumer/message-handler/workers/reap-consumers.worker.js +23 -14
- package/dist/cjs/src/consumer/message-handler/workers/reap-consumers.worker.js.map +1 -1
- package/dist/cjs/src/consumer/message-handler/workers/requeue-delayed.worker.d.ts.map +1 -1
- package/dist/cjs/src/consumer/message-handler/workers/requeue-delayed.worker.js +12 -3
- package/dist/cjs/src/consumer/message-handler/workers/requeue-delayed.worker.js.map +1 -1
- package/dist/cjs/src/consumer/message-handler/workers/requeue-immediate.worker.d.ts.map +1 -1
- package/dist/cjs/src/consumer/message-handler/workers/requeue-immediate.worker.js +9 -3
- package/dist/cjs/src/consumer/message-handler/workers/requeue-immediate.worker.js.map +1 -1
- package/dist/cjs/src/errors/index.d.ts +1 -0
- package/dist/cjs/src/errors/index.d.ts.map +1 -1
- package/dist/cjs/src/errors/index.js +1 -0
- package/dist/cjs/src/errors/index.js.map +1 -1
- package/dist/cjs/src/errors/routing-key-required.error.d.ts +4 -0
- package/dist/cjs/src/errors/routing-key-required.error.d.ts.map +1 -0
- package/dist/cjs/src/errors/routing-key-required.error.js +8 -0
- package/dist/cjs/src/errors/routing-key-required.error.js.map +1 -0
- package/dist/cjs/src/message-manager/_/_requeue-message.d.ts.map +1 -1
- package/dist/cjs/src/message-manager/_/_requeue-message.js +4 -2
- package/dist/cjs/src/message-manager/_/_requeue-message.js.map +1 -1
- package/dist/cjs/src/producer/_/_publish-message.d.ts.map +1 -1
- package/dist/cjs/src/producer/_/_publish-message.js +5 -0
- package/dist/cjs/src/producer/_/_publish-message.js.map +1 -1
- package/dist/cjs/src/producer/producer.d.ts +8 -8
- package/dist/cjs/src/producer/producer.d.ts.map +1 -1
- package/dist/cjs/src/producer/producer.js +104 -120
- package/dist/cjs/src/producer/producer.js.map +1 -1
- package/dist/cjs/src/producer/pub-sub-target-resolver.d.ts +27 -0
- package/dist/cjs/src/producer/pub-sub-target-resolver.d.ts.map +1 -0
- package/dist/cjs/src/producer/pub-sub-target-resolver.js +186 -0
- package/dist/cjs/src/producer/pub-sub-target-resolver.js.map +1 -0
- package/dist/esm/src/common/redis-client/scripts/lua/publish-message.lua +5 -4
- package/dist/esm/src/common/redis-client/scripts/lua/publish-scheduled.lua +142 -107
- package/dist/esm/src/common/redis-client/scripts/lua/requeue-delayed.lua +75 -37
- package/dist/esm/src/common/redis-client/scripts/lua/requeue-immediate.lua +62 -29
- package/dist/esm/src/common/redis-client/scripts/lua/requeue-message.lua +59 -41
- package/dist/esm/src/common/redis-client/scripts/lua/shared-procedures/publish-message.lua +12 -1
- package/dist/esm/src/consumer/message-handler/_/_delete-ephemeral-consumer-group.d.ts +4 -0
- package/dist/esm/src/consumer/message-handler/_/_delete-ephemeral-consumer-group.d.ts.map +1 -0
- package/dist/esm/src/consumer/message-handler/_/_delete-ephemeral-consumer-group.js +8 -0
- package/dist/esm/src/consumer/message-handler/_/_delete-ephemeral-consumer-group.js.map +1 -0
- package/dist/esm/src/consumer/message-handler/_/_generate-ephemeral-consumer-group-id.d.ts +2 -0
- package/dist/esm/src/consumer/message-handler/_/_generate-ephemeral-consumer-group-id.d.ts.map +1 -0
- package/dist/esm/src/consumer/message-handler/_/_generate-ephemeral-consumer-group-id.js +4 -0
- package/dist/esm/src/consumer/message-handler/_/_generate-ephemeral-consumer-group-id.js.map +1 -0
- package/dist/esm/src/consumer/message-handler/_/_prepare-consumer-group.d.ts +4 -0
- package/dist/esm/src/consumer/message-handler/_/_prepare-consumer-group.d.ts.map +1 -0
- package/dist/esm/src/consumer/message-handler/_/_prepare-consumer-group.js +41 -0
- package/dist/esm/src/consumer/message-handler/_/_prepare-consumer-group.js.map +1 -0
- package/dist/esm/src/consumer/message-handler/dequeue-message/dequeue-message.d.ts +1 -3
- package/dist/esm/src/consumer/message-handler/dequeue-message/dequeue-message.d.ts.map +1 -1
- package/dist/esm/src/consumer/message-handler/dequeue-message/dequeue-message.js +3 -44
- package/dist/esm/src/consumer/message-handler/dequeue-message/dequeue-message.js.map +1 -1
- package/dist/esm/src/consumer/message-handler/message-handler.d.ts +8 -6
- package/dist/esm/src/consumer/message-handler/message-handler.d.ts.map +1 -1
- package/dist/esm/src/consumer/message-handler/message-handler.js +80 -18
- package/dist/esm/src/consumer/message-handler/message-handler.js.map +1 -1
- package/dist/esm/src/consumer/message-handler/workers/publish-scheduled.worker.d.ts.map +1 -1
- package/dist/esm/src/consumer/message-handler/workers/publish-scheduled.worker.js +7 -2
- package/dist/esm/src/consumer/message-handler/workers/publish-scheduled.worker.js.map +1 -1
- package/dist/esm/src/consumer/message-handler/workers/reap-consumers.worker.d.ts +1 -0
- package/dist/esm/src/consumer/message-handler/workers/reap-consumers.worker.d.ts.map +1 -1
- package/dist/esm/src/consumer/message-handler/workers/reap-consumers.worker.js +23 -14
- package/dist/esm/src/consumer/message-handler/workers/reap-consumers.worker.js.map +1 -1
- package/dist/esm/src/consumer/message-handler/workers/requeue-delayed.worker.d.ts.map +1 -1
- package/dist/esm/src/consumer/message-handler/workers/requeue-delayed.worker.js +12 -3
- package/dist/esm/src/consumer/message-handler/workers/requeue-delayed.worker.js.map +1 -1
- package/dist/esm/src/consumer/message-handler/workers/requeue-immediate.worker.d.ts.map +1 -1
- package/dist/esm/src/consumer/message-handler/workers/requeue-immediate.worker.js +9 -3
- package/dist/esm/src/consumer/message-handler/workers/requeue-immediate.worker.js.map +1 -1
- package/dist/esm/src/errors/index.d.ts +1 -0
- package/dist/esm/src/errors/index.d.ts.map +1 -1
- package/dist/esm/src/errors/index.js +1 -0
- package/dist/esm/src/errors/index.js.map +1 -1
- package/dist/esm/src/errors/routing-key-required.error.d.ts +4 -0
- package/dist/esm/src/errors/routing-key-required.error.d.ts.map +1 -0
- package/dist/esm/src/errors/routing-key-required.error.js +4 -0
- package/dist/esm/src/errors/routing-key-required.error.js.map +1 -0
- package/dist/esm/src/message-manager/_/_requeue-message.d.ts.map +1 -1
- package/dist/esm/src/message-manager/_/_requeue-message.js +4 -2
- package/dist/esm/src/message-manager/_/_requeue-message.js.map +1 -1
- package/dist/esm/src/producer/_/_publish-message.d.ts.map +1 -1
- package/dist/esm/src/producer/_/_publish-message.js +6 -1
- package/dist/esm/src/producer/_/_publish-message.js.map +1 -1
- package/dist/esm/src/producer/producer.d.ts +8 -8
- package/dist/esm/src/producer/producer.d.ts.map +1 -1
- package/dist/esm/src/producer/producer.js +105 -121
- package/dist/esm/src/producer/producer.js.map +1 -1
- package/dist/esm/src/producer/pub-sub-target-resolver.d.ts +27 -0
- package/dist/esm/src/producer/pub-sub-target-resolver.d.ts.map +1 -0
- package/dist/esm/src/producer/pub-sub-target-resolver.js +184 -0
- package/dist/esm/src/producer/pub-sub-target-resolver.js.map +1 -0
- package/package.json +2 -2
- package/dist/cjs/src/producer/queue-consumer-groups-cache.d.ts +0 -27
- package/dist/cjs/src/producer/queue-consumer-groups-cache.d.ts.map +0 -1
- package/dist/cjs/src/producer/queue-consumer-groups-cache.js +0 -212
- package/dist/cjs/src/producer/queue-consumer-groups-cache.js.map +0 -1
- package/dist/esm/src/producer/queue-consumer-groups-cache.d.ts +0 -27
- package/dist/esm/src/producer/queue-consumer-groups-cache.d.ts.map +0 -1
- package/dist/esm/src/producer/queue-consumer-groups-cache.js +0 -211
- package/dist/esm/src/producer/queue-consumer-groups-cache.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,34 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [9.0.0-next.9](https://github.com/weyoss/redis-smq/compare/v9.0.0-next.8...v9.0.0-next.9) (2025-10-21)
|
|
7
|
+
|
|
8
|
+
### 🐛 Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **redis-smq:** add missing RoutingKeyRequiredError class ([2a76b66](https://github.com/weyoss/redis-smq/commit/2a76b668a698cd79f8cb437a642d5062067cd149))
|
|
11
|
+
|
|
12
|
+
### 📝 Documentation
|
|
13
|
+
|
|
14
|
+
- **redis-smq:** update documentation and improve md formatting ([c659b9f](https://github.com/weyoss/redis-smq/commit/c659b9f8f4b026d731ddaf94228ce871ee56f14a))
|
|
15
|
+
|
|
16
|
+
### ♻️ Code Refactoring
|
|
17
|
+
|
|
18
|
+
- **redis-smq:** rename QueueConsumerGroupsCache to PubSubTargetResolver, clean up Producer docs ([1ea5669](https://github.com/weyoss/redis-smq/commit/1ea566959e97b0b695cea85b9f2117903273320d))
|
|
19
|
+
|
|
20
|
+
## [9.0.0-next.8](https://github.com/weyoss/redis-smq/compare/v9.0.0-next.7...v9.0.0-next.8) (2025-10-18)
|
|
21
|
+
|
|
22
|
+
### ✨ Features
|
|
23
|
+
|
|
24
|
+
- **redis-smq:** make consumerGroupId optional for PubSub queue consumers ([0529efd](https://github.com/weyoss/redis-smq/commit/0529efd3ab38ba6f423143af344b30d2ef1cc4a4))
|
|
25
|
+
|
|
26
|
+
### 🐛 Bug Fixes
|
|
27
|
+
|
|
28
|
+
- **redis-smq:** check consumer group existence when relevant ([1711ac1](https://github.com/weyoss/redis-smq/commit/1711ac1db83ae8ca1e65947c33ca2878f49e15ed))
|
|
29
|
+
|
|
30
|
+
### 📝 Documentation
|
|
31
|
+
|
|
32
|
+
- **redis-smq:** clarify consumer group behavior for PubSub queues ([84f0e48](https://github.com/weyoss/redis-smq/commit/84f0e484bdca19085d067d738bb9d1adaa825ca1))
|
|
33
|
+
|
|
6
34
|
## [9.0.0-next.7](https://github.com/weyoss/redis-smq/compare/v9.0.0-next.6...v9.0.0-next.7) (2025-10-13)
|
|
7
35
|
|
|
8
36
|
**Note:** Version bump only for package redis-smq
|
|
@@ -8,13 +8,14 @@
|
|
|
8
8
|
-- KEYS[3]: keyQueuePending
|
|
9
9
|
-- KEYS[4]: keyQueueScheduled
|
|
10
10
|
-- KEYS[5]: keyQueueMessages
|
|
11
|
-
-- KEYS[6]:
|
|
11
|
+
-- KEYS[6]: keyQueueConsumerGroups
|
|
12
|
+
-- KEYS[7]: keyMessage
|
|
12
13
|
--
|
|
13
14
|
-- ARGV layout:
|
|
14
15
|
-- ARGV[1-11]: Queue property keys and scheduling values
|
|
15
|
-
-- ARGV[12-34]: Message property keys (
|
|
16
|
-
-- ARGV[35-57]: Message property values (
|
|
17
|
-
|
|
16
|
+
-- ARGV[12-34]: Message property keys (23 keys)
|
|
17
|
+
-- ARGV[35-57]: Message property values (23 values)
|
|
18
|
+
-- ARGV[58]: consumerGroupId
|
|
18
19
|
--
|
|
19
20
|
-- This script depends on 'shared-procedures/publish-message.lua'.
|
|
20
21
|
-- The content of 'shared-procedures/publish-message.lua' must be prepended to this script before loading it into Redis.
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
-- Description:
|
|
2
2
|
-- Publishes due scheduled messages for a SINGLE queue. This script handles two cases:
|
|
3
|
-
-- 1. Simple scheduled message: The message is moved to the pending queue.
|
|
4
|
-
-- 2. Repeating scheduled message: A new message is created and published, and the
|
|
3
|
+
-- 1. Simple scheduled message: The message is moved to the pending queue. If the target consumer group is gone, it is moved to the dead-letter queue.
|
|
4
|
+
-- 2. Repeating scheduled message: A new message is created and published. If the target consumer group is gone, the original repeating message is dead-lettered to terminate its cycle, and the new message for the current firing is discarded.
|
|
5
5
|
--
|
|
6
6
|
-- This script depends on 'shared-procedures/publish-message.lua'.
|
|
7
7
|
-- The content of 'shared-procedures/publish-message.lua' must be prepended to this script before loading it into Redis.
|
|
8
8
|
--
|
|
9
9
|
-- KEYS:
|
|
10
|
-
-- Static Keys (1-
|
|
10
|
+
-- Static Keys (1-7):
|
|
11
11
|
-- KEYS[1]: keyQueueProperties
|
|
12
12
|
-- KEYS[2]: keyQueuePending
|
|
13
13
|
-- KEYS[3]: keyQueueMessages
|
|
14
14
|
-- KEYS[4]: keyQueuePriorityPending
|
|
15
15
|
-- KEYS[5]: keyQueueScheduled
|
|
16
|
-
--
|
|
16
|
+
-- KEYS[6]: keyQueueDeadLettered
|
|
17
|
+
-- KEYS[7]: keyQueueConsumerGroups
|
|
18
|
+
-- Dynamic Keys (8...): A repeating pair for each message.
|
|
17
19
|
-- - keyMessage (for the new message, or an empty placeholder)
|
|
18
20
|
-- - keyScheduledMessage (for the original message)
|
|
19
21
|
--
|
|
20
22
|
-- ARGV:
|
|
21
|
-
-- ARGV[1-
|
|
22
|
-
-- ARGV[
|
|
23
|
+
-- ARGV[1-34]: A list of all EQueueProperty and EMessageProperty constants.
|
|
24
|
+
-- ARGV[35...]: A flat list of repeating parameters for each message.
|
|
23
25
|
--
|
|
24
|
-
-- ARGV structure per message (
|
|
26
|
+
-- ARGV structure per message (13 parameters):
|
|
25
27
|
-- 1. messageId (new message ID, or '')
|
|
26
28
|
-- 2. message (new message body, or '')
|
|
27
29
|
-- 3. messagePriority
|
|
@@ -34,6 +36,7 @@
|
|
|
34
36
|
-- 10. scheduledMessageCronFired
|
|
35
37
|
-- 11. scheduledMessageRepeatCount
|
|
36
38
|
-- 12. scheduledMessageEffectiveScheduledDelay
|
|
39
|
+
-- 13. consumerGroupId
|
|
37
40
|
--
|
|
38
41
|
-- Returns:
|
|
39
42
|
-- - The number of successfully processed messages.
|
|
@@ -45,6 +48,8 @@ local keyQueuePending = KEYS[2]
|
|
|
45
48
|
local keyQueueMessages = KEYS[3]
|
|
46
49
|
local keyQueuePriorityPending = KEYS[4]
|
|
47
50
|
local keyQueueScheduled = KEYS[5]
|
|
51
|
+
local keyQueueDeadLettered = KEYS[6]
|
|
52
|
+
local keyQueueConsumerGroups = KEYS[7]
|
|
48
53
|
|
|
49
54
|
-- Early exit if the queue does not exist. This check is now done only once per batch.
|
|
50
55
|
local queueType = redis.call("HGET", keyQueueProperties, ARGV[1] -- EQueuePropertyQueueType
|
|
@@ -53,48 +58,50 @@ if queueType == false then
|
|
|
53
58
|
return 0
|
|
54
59
|
end
|
|
55
60
|
|
|
56
|
-
-- Queue Property Constants (ARGV[1-
|
|
61
|
+
-- Queue Property Constants (ARGV[1-8])
|
|
57
62
|
local EQueuePropertyQueueType = ARGV[1]
|
|
58
63
|
local EQueuePropertyMessagesCount = ARGV[2]
|
|
59
64
|
local EQueuePropertyPendingMessagesCount = ARGV[3]
|
|
60
65
|
local EQueuePropertyScheduledMessagesCount = ARGV[4]
|
|
61
|
-
local
|
|
62
|
-
local
|
|
63
|
-
local
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
local
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
local
|
|
73
|
-
local
|
|
74
|
-
local
|
|
75
|
-
local
|
|
76
|
-
local
|
|
77
|
-
local
|
|
78
|
-
local
|
|
79
|
-
local
|
|
80
|
-
local
|
|
81
|
-
local
|
|
82
|
-
local
|
|
83
|
-
local
|
|
84
|
-
local
|
|
85
|
-
local
|
|
86
|
-
local
|
|
87
|
-
local
|
|
88
|
-
local
|
|
89
|
-
local
|
|
90
|
-
local
|
|
91
|
-
local
|
|
92
|
-
local
|
|
66
|
+
local EQueuePropertyDeadLetteredMessagesCount = ARGV[5]
|
|
67
|
+
local EQueuePropertyQueueTypePriorityQueue = ARGV[6]
|
|
68
|
+
local EQueuePropertyQueueTypeLIFOQueue = ARGV[7]
|
|
69
|
+
local EQueuePropertyQueueTypeFIFOQueue = ARGV[8]
|
|
70
|
+
|
|
71
|
+
-- Message Status Constants (ARGV[9-11])
|
|
72
|
+
local EMessagePropertyStatusPending = ARGV[9]
|
|
73
|
+
local EMessagePropertyStatusScheduled = ARGV[10]
|
|
74
|
+
local EMessagePropertyStatusDeadLettered = ARGV[11]
|
|
75
|
+
|
|
76
|
+
-- Message Property Constants (ARGV[12-34])
|
|
77
|
+
local EMessagePropertyId = ARGV[12]
|
|
78
|
+
local EMessagePropertyStatus = ARGV[13]
|
|
79
|
+
local EMessagePropertyMessage = ARGV[14]
|
|
80
|
+
local EMessagePropertyScheduledAt = ARGV[15]
|
|
81
|
+
local EMessagePropertyPublishedAt = ARGV[16]
|
|
82
|
+
local EMessagePropertyProcessingStartedAt = ARGV[17]
|
|
83
|
+
local EMessagePropertyDeadLetteredAt = ARGV[18]
|
|
84
|
+
local EMessagePropertyAcknowledgedAt = ARGV[19]
|
|
85
|
+
local EMessagePropertyUnacknowledgedAt = ARGV[20]
|
|
86
|
+
local EMessagePropertyLastUnacknowledgedAt = ARGV[21]
|
|
87
|
+
local EMessagePropertyLastScheduledAt = ARGV[22]
|
|
88
|
+
local EMessagePropertyRequeuedAt = ARGV[23]
|
|
89
|
+
local EMessagePropertyRequeueCount = ARGV[24]
|
|
90
|
+
local EMessagePropertyLastRequeuedAt = ARGV[25]
|
|
91
|
+
local EMessagePropertyLastRetriedAttemptAt = ARGV[26]
|
|
92
|
+
local EMessagePropertyScheduledCronFired = ARGV[27]
|
|
93
|
+
local EMessagePropertyAttempts = ARGV[28]
|
|
94
|
+
local EMessagePropertyScheduledRepeatCount = ARGV[29]
|
|
95
|
+
local EMessagePropertyExpired = ARGV[30]
|
|
96
|
+
local EMessagePropertyEffectiveScheduledDelay = ARGV[31]
|
|
97
|
+
local EMessagePropertyScheduledTimes = ARGV[32]
|
|
98
|
+
local EMessagePropertyScheduledMessageParentId = ARGV[33]
|
|
99
|
+
local EMessagePropertyRequeuedMessageParentId = ARGV[34]
|
|
93
100
|
|
|
94
101
|
-- Loop constants
|
|
95
|
-
local INITIAL_ARGV_OFFSET =
|
|
96
|
-
local INITIAL_KEY_OFFSET =
|
|
97
|
-
local PARAMS_PER_MESSAGE =
|
|
102
|
+
local INITIAL_ARGV_OFFSET = 34
|
|
103
|
+
local INITIAL_KEY_OFFSET = 7
|
|
104
|
+
local PARAMS_PER_MESSAGE = 14
|
|
98
105
|
local KEYS_PER_MESSAGE = 2
|
|
99
106
|
local keyIndex = INITIAL_KEY_OFFSET + 1
|
|
100
107
|
local processed_count = 0
|
|
@@ -113,83 +120,111 @@ for argvIndex = INITIAL_ARGV_OFFSET + 1, #ARGV, PARAMS_PER_MESSAGE do
|
|
|
113
120
|
local scheduledMessageCronFired = ARGV[argvIndex + 9]
|
|
114
121
|
local scheduledMessageRepeatCount = ARGV[argvIndex + 10]
|
|
115
122
|
local scheduledMessageEffectiveScheduledDelay = ARGV[argvIndex + 11]
|
|
123
|
+
local consumerGroupId = ARGV[argvIndex + 12]
|
|
124
|
+
local messageDeadLetteredAt = ARGV[argvIndex + 13]
|
|
116
125
|
|
|
117
126
|
-- Extract keys for the current message
|
|
118
127
|
local keyMessage = KEYS[keyIndex]
|
|
119
128
|
local keyScheduledMessage = KEYS[keyIndex + 1]
|
|
120
129
|
keyIndex = keyIndex + KEYS_PER_MESSAGE
|
|
121
130
|
|
|
131
|
+
local group_exists = true
|
|
132
|
+
if consumerGroupId and consumerGroupId ~= '' then
|
|
133
|
+
if redis.call("SISMEMBER", keyQueueConsumerGroups, consumerGroupId) == 0 then
|
|
134
|
+
group_exists = false
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
122
138
|
-- Case 1: A simple scheduled message is due. Move it to the pending queue.
|
|
123
139
|
if newMessageId == '' then
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
140
|
+
-- Always remove from scheduled queue first
|
|
141
|
+
if redis.call("ZREM", keyQueueScheduled, scheduledMessageId) == 1 then
|
|
142
|
+
redis.call("HINCRBY", keyQueueProperties, EQueuePropertyScheduledMessagesCount, -1)
|
|
143
|
+
|
|
144
|
+
if group_exists then
|
|
145
|
+
if queueType == EQueuePropertyQueueTypeFIFOQueue then
|
|
146
|
+
redis.call("LPUSH", keyQueuePending, scheduledMessageId)
|
|
147
|
+
elseif queueType == EQueuePropertyQueueTypeLIFOQueue then
|
|
148
|
+
redis.call("RPUSH", keyQueuePending, scheduledMessageId)
|
|
149
|
+
else -- Priority queue
|
|
150
|
+
redis.call("ZADD", keyQueuePriorityPending, newMessagePriority, scheduledMessageId)
|
|
151
|
+
end
|
|
152
|
+
redis.call("HINCRBY", keyQueueProperties, EQueuePropertyPendingMessagesCount, 1)
|
|
153
|
+
|
|
154
|
+
-- Update all relevant properties for the scheduled message
|
|
155
|
+
redis.call(
|
|
156
|
+
"HSET", keyScheduledMessage,
|
|
157
|
+
EMessagePropertyPublishedAt, scheduledMessagePublishedAt,
|
|
158
|
+
EMessagePropertyStatus, EMessagePropertyStatusPending,
|
|
159
|
+
EMessagePropertyLastScheduledAt, scheduledMessageLastScheduledAt,
|
|
160
|
+
EMessagePropertyScheduledTimes, scheduledMessageScheduledTimes,
|
|
161
|
+
EMessagePropertyScheduledCronFired, scheduledMessageCronFired,
|
|
162
|
+
EMessagePropertyScheduledRepeatCount, scheduledMessageRepeatCount,
|
|
163
|
+
EMessagePropertyEffectiveScheduledDelay, scheduledMessageEffectiveScheduledDelay
|
|
164
|
+
)
|
|
165
|
+
else
|
|
166
|
+
-- Group does not exist, dead-letter the message
|
|
167
|
+
redis.call("RPUSH", keyQueueDeadLettered, scheduledMessageId)
|
|
168
|
+
redis.call("HINCRBY", keyQueueProperties, EQueuePropertyDeadLetteredMessagesCount, 1)
|
|
169
|
+
redis.call(
|
|
170
|
+
"HSET", keyScheduledMessage,
|
|
171
|
+
EMessagePropertyStatus, EMessagePropertyStatusDeadLettered,
|
|
172
|
+
EMessagePropertyDeadLetteredAt, messageDeadLetteredAt)
|
|
173
|
+
end
|
|
174
|
+
processed_count = processed_count + 1
|
|
130
175
|
end
|
|
131
|
-
redis.call("ZREM", keyQueueScheduled, scheduledMessageId)
|
|
132
|
-
redis.call("HINCRBY", keyQueueProperties, EQueuePropertyPendingMessagesCount, 1)
|
|
133
|
-
redis.call("HINCRBY", keyQueueProperties, EQueuePropertyScheduledMessagesCount, -1)
|
|
134
|
-
|
|
135
|
-
-- Update all relevant properties for the scheduled message
|
|
136
|
-
redis.call(
|
|
137
|
-
"HSET", keyScheduledMessage,
|
|
138
|
-
EMessagePropertyPublishedAt, scheduledMessagePublishedAt,
|
|
139
|
-
EMessagePropertyStatus, EMessagePropertyStatusPending,
|
|
140
|
-
EMessagePropertyLastScheduledAt, scheduledMessageLastScheduledAt,
|
|
141
|
-
EMessagePropertyScheduledTimes, scheduledMessageScheduledTimes,
|
|
142
|
-
EMessagePropertyScheduledCronFired, scheduledMessageCronFired,
|
|
143
|
-
EMessagePropertyScheduledRepeatCount, scheduledMessageRepeatCount,
|
|
144
|
-
EMessagePropertyEffectiveScheduledDelay, scheduledMessageEffectiveScheduledDelay
|
|
145
|
-
)
|
|
146
|
-
processed_count = processed_count + 1
|
|
147
176
|
else
|
|
148
|
-
-- Case 2: A repeating message is due.
|
|
149
|
-
if
|
|
150
|
-
--
|
|
151
|
-
|
|
152
|
-
redis.call("ZREM", keyQueueScheduled, scheduledMessageId)
|
|
153
|
-
else
|
|
177
|
+
-- Case 2: A repeating message is due.
|
|
178
|
+
if group_exists then
|
|
179
|
+
-- Group exists: Publish a new message and reschedule the original.
|
|
180
|
+
|
|
154
181
|
-- Reschedule the original message for its next occurrence
|
|
155
182
|
redis.call("ZADD", keyQueueScheduled, scheduledMessageNextScheduleTimestamp, scheduledMessageId)
|
|
156
|
-
end
|
|
157
183
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
184
|
+
-- Update all relevant properties for the original scheduled message
|
|
185
|
+
redis.call(
|
|
186
|
+
"HSET", keyScheduledMessage,
|
|
187
|
+
EMessagePropertyLastScheduledAt, scheduledMessageLastScheduledAt,
|
|
188
|
+
EMessagePropertyScheduledTimes, scheduledMessageScheduledTimes,
|
|
189
|
+
EMessagePropertyScheduledCronFired, scheduledMessageCronFired,
|
|
190
|
+
EMessagePropertyScheduledRepeatCount, scheduledMessageRepeatCount,
|
|
191
|
+
EMessagePropertyEffectiveScheduledDelay, scheduledMessageEffectiveScheduledDelay
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
-- Publishing the new message
|
|
195
|
+
local pKeys = {
|
|
196
|
+
keyQueueProperties,
|
|
197
|
+
keyQueuePriorityPending,
|
|
198
|
+
keyQueuePending,
|
|
199
|
+
keyQueueScheduled,
|
|
200
|
+
keyQueueMessages,
|
|
201
|
+
keyQueueConsumerGroups,
|
|
202
|
+
keyMessage
|
|
203
|
+
}
|
|
204
|
+
local pArgs = {
|
|
205
|
+
EQueuePropertyQueueType, EQueuePropertyMessagesCount, EQueuePropertyPendingMessagesCount, EQueuePropertyScheduledMessagesCount, EQueuePropertyQueueTypePriorityQueue, EQueuePropertyQueueTypeLIFOQueue, EQueuePropertyQueueTypeFIFOQueue,
|
|
206
|
+
newMessagePriority, '', EMessagePropertyStatusScheduled, EMessagePropertyStatusPending,
|
|
207
|
+
EMessagePropertyId, EMessagePropertyStatus, EMessagePropertyMessage, EMessagePropertyScheduledAt, EMessagePropertyPublishedAt, EMessagePropertyProcessingStartedAt, EMessagePropertyDeadLetteredAt, EMessagePropertyAcknowledgedAt, EMessagePropertyUnacknowledgedAt, EMessagePropertyLastUnacknowledgedAt, EMessagePropertyLastScheduledAt, EMessagePropertyRequeuedAt, EMessagePropertyRequeueCount, EMessagePropertyLastRequeuedAt, EMessagePropertyLastRetriedAttemptAt, EMessagePropertyScheduledCronFired, EMessagePropertyAttempts, EMessagePropertyScheduledRepeatCount, EMessagePropertyExpired, EMessagePropertyEffectiveScheduledDelay, EMessagePropertyScheduledTimes, EMessagePropertyScheduledMessageParentId, EMessagePropertyRequeuedMessageParentId,
|
|
208
|
+
newMessageId, EMessagePropertyStatusPending, newMessage, '', newMessagePublishedAt, '', '', '', '', '', '', '', '0', '', '', '0', '0', '0', '0', '0', '0', scheduledMessageId, '',
|
|
209
|
+
consumerGroupId
|
|
210
|
+
}
|
|
211
|
+
local result = publish_message(pKeys, pArgs)
|
|
212
|
+
if result ~= 'OK' then
|
|
213
|
+
return 'PUBLISH_ERROR:' .. newMessageId .. ':' .. result
|
|
214
|
+
end
|
|
215
|
+
else
|
|
216
|
+
-- Group does not exist. Dead-letter the original repeating message to stop its cycle.
|
|
217
|
+
-- The new message for this firing is simply discarded.
|
|
218
|
+
if redis.call("ZREM", keyQueueScheduled, scheduledMessageId) == 1 then
|
|
219
|
+
redis.call("RPUSH", keyQueueDeadLettered, scheduledMessageId)
|
|
220
|
+
redis.call(
|
|
221
|
+
"HSET", keyScheduledMessage,
|
|
222
|
+
EMessagePropertyStatus, EMessagePropertyStatusDeadLettered,
|
|
223
|
+
EMessagePropertyDeadLetteredAt, messageDeadLetteredAt
|
|
224
|
+
)
|
|
225
|
+
redis.call("HINCRBY", keyQueueProperties, EQueuePropertyScheduledMessagesCount, -1)
|
|
226
|
+
redis.call("HINCRBY", keyQueueProperties, EQueuePropertyDeadLetteredMessagesCount, 1)
|
|
227
|
+
end
|
|
193
228
|
end
|
|
194
229
|
processed_count = processed_count + 1
|
|
195
230
|
end
|
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
-- Description:
|
|
2
1
|
-- Re-queues messages from the delayed sorted set to the pending queue.
|
|
3
2
|
-- This script is designed for batch processing to improve performance. It moves messages
|
|
4
3
|
-- that are due for a retry back into the active processing queue.
|
|
5
4
|
-- It atomically removes messages from the delayed queue to prevent race conditions
|
|
6
5
|
-- and updates message status and the 'lastRetriedAttemptAt' timestamp.
|
|
7
6
|
-- It supports FIFO, LIFO, and Priority queues.
|
|
7
|
+
-- For PUB/SUB queues, if a message's target consumer group has been deleted,
|
|
8
|
+
-- the message is moved to the dead-letter queue instead of being re-queued.
|
|
8
9
|
-- Queue counters are updated once per batch for efficiency.
|
|
9
10
|
--
|
|
10
11
|
-- KEYS:
|
|
11
|
-
-- Static Keys (1-
|
|
12
|
+
-- Static Keys (1-4):
|
|
12
13
|
-- KEYS[1]: keyQueueProperties (HMAP)
|
|
13
14
|
-- KEYS[2]: keyQueueDelayed (ZSET)
|
|
14
|
-
--
|
|
15
|
+
-- KEYS[3]: keyQueueDeadLettered (LIST)
|
|
16
|
+
-- KEYS[4]: keyQueueConsumerGroups (SET)
|
|
17
|
+
-- Dynamic Keys (5...):
|
|
15
18
|
-- A flat list of repeating keys for each message.
|
|
16
19
|
--
|
|
17
20
|
-- KEYS structure per message (3 keys):
|
|
@@ -20,33 +23,39 @@
|
|
|
20
23
|
-- 3. keyQueuePriorityPending (for Priority)
|
|
21
24
|
--
|
|
22
25
|
-- ARGV:
|
|
23
|
-
-- Static ARGV (1-
|
|
24
|
-
-- ARGV[1-
|
|
25
|
-
-- ARGV[
|
|
26
|
-
-- Dynamic ARGV (
|
|
26
|
+
-- Static ARGV (1-12):
|
|
27
|
+
-- ARGV[1-11]: A list of all EQueueProperty and EMessageProperty constants.
|
|
28
|
+
-- ARGV[12]: Current timestamp.
|
|
29
|
+
-- Dynamic ARGV (13...):
|
|
27
30
|
-- A flat list of repeating parameters for each message.
|
|
28
31
|
--
|
|
29
|
-
-- ARGV structure per message (
|
|
32
|
+
-- ARGV structure per message (3 parameters):
|
|
30
33
|
-- 1. messageId
|
|
31
34
|
-- 2. messagePriority
|
|
35
|
+
-- 3. consumerGroupId
|
|
32
36
|
--
|
|
33
37
|
-- Returns:
|
|
34
|
-
-- - The number of messages successfully processed
|
|
38
|
+
-- - The number of messages successfully processed (re-queued or dead-lettered).
|
|
35
39
|
|
|
36
40
|
-- Static Keys
|
|
37
41
|
local keyQueueProperties = KEYS[1]
|
|
38
42
|
local keyQueueDelayed = KEYS[2]
|
|
43
|
+
local keyQueueDeadLettered = KEYS[3]
|
|
44
|
+
local keyQueueConsumerGroups = KEYS[4]
|
|
39
45
|
|
|
40
46
|
-- Static ARGV
|
|
41
47
|
local EQueuePropertyQueueType = ARGV[1]
|
|
42
48
|
local EQueuePropertyDelayedMessagesCount = ARGV[2]
|
|
43
49
|
local EQueuePropertyPendingMessagesCount = ARGV[3]
|
|
44
|
-
local
|
|
45
|
-
local
|
|
46
|
-
local
|
|
47
|
-
local
|
|
48
|
-
local
|
|
49
|
-
local
|
|
50
|
+
local EQueuePropertyDeadLetteredMessagesCount = ARGV[4]
|
|
51
|
+
local EMessagePropertyStatus = ARGV[5]
|
|
52
|
+
local EMessagePropertyStatusPending = ARGV[6]
|
|
53
|
+
local EMessagePropertyStatusDeadLettered = ARGV[7]
|
|
54
|
+
local EMessagePropertyDeadLetteredAt = ARGV[8]
|
|
55
|
+
local EMessagePropertyLastRetriedAttemptAt = ARGV[9]
|
|
56
|
+
local EQueuePropertyQueueTypeLIFOQueue = ARGV[10]
|
|
57
|
+
local EQueuePropertyQueueTypeFIFOQueue = ARGV[11]
|
|
58
|
+
local timestamp = ARGV[12]
|
|
50
59
|
|
|
51
60
|
-- Early exit if the queue does not exist
|
|
52
61
|
local queueType = redis.call("HGET", keyQueueProperties, EQueuePropertyQueueType)
|
|
@@ -55,19 +64,21 @@ if queueType == false then
|
|
|
55
64
|
end
|
|
56
65
|
|
|
57
66
|
-- Constants for parameter counts
|
|
58
|
-
local INITIAL_KEY_OFFSET =
|
|
59
|
-
local INITIAL_ARGV_OFFSET =
|
|
60
|
-
local PARAMS_PER_MESSAGE =
|
|
67
|
+
local INITIAL_KEY_OFFSET = 4
|
|
68
|
+
local INITIAL_ARGV_OFFSET = 12
|
|
69
|
+
local PARAMS_PER_MESSAGE = 3
|
|
61
70
|
local KEYS_PER_MESSAGE = 3
|
|
62
71
|
|
|
63
72
|
local keyIndex = INITIAL_KEY_OFFSET + 1
|
|
64
|
-
local
|
|
73
|
+
local requeued_count = 0
|
|
74
|
+
local dead_lettered_count = 0
|
|
65
75
|
|
|
66
76
|
-- Process messages in batches
|
|
67
77
|
for argvIndex = INITIAL_ARGV_OFFSET + 1, #ARGV, PARAMS_PER_MESSAGE do
|
|
68
78
|
-- Extract message parameters
|
|
69
79
|
local messageId = ARGV[argvIndex]
|
|
70
80
|
local messagePriority = ARGV[argvIndex + 1]
|
|
81
|
+
local consumerGroupId = ARGV[argvIndex + 2]
|
|
71
82
|
|
|
72
83
|
-- Get the message keys for this iteration from KEYS
|
|
73
84
|
local keyMessage = KEYS[keyIndex]
|
|
@@ -79,30 +90,57 @@ for argvIndex = INITIAL_ARGV_OFFSET + 1, #ARGV, PARAMS_PER_MESSAGE do
|
|
|
79
90
|
-- If ZREM returns 0, the message was not found (e.g., already processed),
|
|
80
91
|
-- so we skip it to prevent corrupting queue counters.
|
|
81
92
|
if redis.call("ZREM", keyQueueDelayed, messageId) == 1 then
|
|
82
|
-
|
|
83
|
-
if
|
|
84
|
-
redis.call("
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
else -- Priority queue
|
|
88
|
-
redis.call("ZADD", keyQueuePriorityPending, messagePriority, messageId)
|
|
93
|
+
local group_exists = true
|
|
94
|
+
if consumerGroupId and consumerGroupId ~= '' then
|
|
95
|
+
if redis.call("SISMEMBER", keyQueueConsumerGroups, consumerGroupId) == 0 then
|
|
96
|
+
group_exists = false
|
|
97
|
+
end
|
|
89
98
|
end
|
|
90
99
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
if group_exists then
|
|
101
|
+
-- Move the message to the pending queue.
|
|
102
|
+
if queueType == EQueuePropertyQueueTypeFIFOQueue then
|
|
103
|
+
redis.call("LPUSH", keyQueuePending, messageId)
|
|
104
|
+
elseif queueType == EQueuePropertyQueueTypeLIFOQueue then
|
|
105
|
+
redis.call("RPUSH", keyQueuePending, messageId)
|
|
106
|
+
else -- Priority queue
|
|
107
|
+
redis.call("ZADD", keyQueuePriorityPending, messagePriority, messageId)
|
|
108
|
+
end
|
|
96
109
|
|
|
97
|
-
|
|
110
|
+
-- Update message properties
|
|
111
|
+
redis.call("HSET", keyMessage,
|
|
112
|
+
EMessagePropertyStatus, EMessagePropertyStatusPending,
|
|
113
|
+
EMessagePropertyLastRetriedAttemptAt, timestamp
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
requeued_count = requeued_count + 1
|
|
117
|
+
else
|
|
118
|
+
-- The consumer group does not exist. Dead-letter the message.
|
|
119
|
+
redis.call("RPUSH", keyQueueDeadLettered, messageId)
|
|
120
|
+
|
|
121
|
+
-- Update message properties
|
|
122
|
+
redis.call("HSET", keyMessage,
|
|
123
|
+
EMessagePropertyStatus, EMessagePropertyStatusDeadLettered,
|
|
124
|
+
EMessagePropertyDeadLetteredAt, timestamp
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
dead_lettered_count = dead_lettered_count + 1
|
|
128
|
+
end
|
|
98
129
|
end
|
|
99
130
|
end
|
|
100
131
|
|
|
101
132
|
-- After processing the whole batch, update queue counters once.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
133
|
+
if requeued_count > 0 then
|
|
134
|
+
redis.call("HINCRBY", keyQueueProperties, EQueuePropertyPendingMessagesCount, requeued_count)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
if dead_lettered_count > 0 then
|
|
138
|
+
redis.call("HINCRBY", keyQueueProperties, EQueuePropertyDeadLetteredMessagesCount, dead_lettered_count)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
local total_processed = requeued_count + dead_lettered_count
|
|
142
|
+
if total_processed > 0 then
|
|
143
|
+
redis.call("HINCRBY", keyQueueProperties, EQueuePropertyDelayedMessagesCount, -total_processed)
|
|
106
144
|
end
|
|
107
145
|
|
|
108
|
-
return
|
|
146
|
+
return total_processed
|