redqueue 0.13.1__tar.gz → 0.14.0__tar.gz

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.
Files changed (60) hide show
  1. {redqueue-0.13.1 → redqueue-0.14.0}/CHANGELOG.md +33 -15
  2. {redqueue-0.13.1 → redqueue-0.14.0}/PKG-INFO +30 -7
  3. {redqueue-0.13.1 → redqueue-0.14.0}/README-zh-CN.md +38 -18
  4. {redqueue-0.13.1 → redqueue-0.14.0}/README.md +42 -19
  5. {redqueue-0.13.1 → redqueue-0.14.0}/docs/API.md +54 -17
  6. redqueue-0.14.0/docs/superpowers/plans/2026-06-27-message-deduplication.md +357 -0
  7. redqueue-0.14.0/docs/superpowers/specs/2026-06-27-message-deduplication-design.md +170 -0
  8. {redqueue-0.13.1 → redqueue-0.14.0}/pyproject.toml +2 -2
  9. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/__init__.py +4 -3
  10. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/_version.py +1 -1
  11. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/async_client.py +117 -52
  12. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/client.py +109 -51
  13. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/config.py +30 -0
  14. redqueue-0.14.0/src/redqueue/deduplication.py +334 -0
  15. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/message.py +16 -16
  16. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/monitoring.py +4 -3
  17. {redqueue-0.13.1 → redqueue-0.14.0}/tests/fakes.py +68 -26
  18. {redqueue-0.13.1 → redqueue-0.14.0}/tests/test_project_skeleton.py +346 -138
  19. {redqueue-0.13.1 → redqueue-0.14.0}/tests/test_real_redis_availability.py +68 -5
  20. {redqueue-0.13.1 → redqueue-0.14.0}/.github/workflows/ci.yml +0 -0
  21. {redqueue-0.13.1 → redqueue-0.14.0}/.gitignore +0 -0
  22. {redqueue-0.13.1 → redqueue-0.14.0}/CODE_OF_CONDUCT.md +0 -0
  23. {redqueue-0.13.1 → redqueue-0.14.0}/CONTRIBUTING.md +0 -0
  24. {redqueue-0.13.1 → redqueue-0.14.0}/LICENSE +0 -0
  25. {redqueue-0.13.1 → redqueue-0.14.0}/NOTICE +0 -0
  26. {redqueue-0.13.1 → redqueue-0.14.0}/docs/RELEASE.md +0 -0
  27. {redqueue-0.13.1 → redqueue-0.14.0}/examples/README.md +0 -0
  28. {redqueue-0.13.1 → redqueue-0.14.0}/examples/__init__.py +0 -0
  29. {redqueue-0.13.1 → redqueue-0.14.0}/examples/async_list_queue.py +0 -0
  30. {redqueue-0.13.1 → redqueue-0.14.0}/examples/common.py +0 -0
  31. {redqueue-0.13.1 → redqueue-0.14.0}/examples/compatibility_check.py +0 -0
  32. {redqueue-0.13.1 → redqueue-0.14.0}/examples/custom_serializer.py +0 -0
  33. {redqueue-0.13.1 → redqueue-0.14.0}/examples/delayed_tasks.py +0 -0
  34. {redqueue-0.13.1 → redqueue-0.14.0}/examples/monitoring_hooks.py +0 -0
  35. {redqueue-0.13.1 → redqueue-0.14.0}/examples/stream_queue.py +0 -0
  36. {redqueue-0.13.1 → redqueue-0.14.0}/examples/sync_list_queue.py +0 -0
  37. {redqueue-0.13.1 → redqueue-0.14.0}/requirements.txt +0 -0
  38. {redqueue-0.13.1 → redqueue-0.14.0}/scripts/check.py +0 -0
  39. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/__main__.py +0 -0
  40. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/backends/__init__.py +0 -0
  41. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/backends/async_delay.py +0 -0
  42. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/backends/async_list.py +0 -0
  43. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/backends/async_stream.py +0 -0
  44. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/backends/base.py +0 -0
  45. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/backends/delay.py +0 -0
  46. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/backends/list.py +0 -0
  47. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/backends/stream.py +0 -0
  48. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/cli.py +0 -0
  49. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/compat.py +0 -0
  50. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/connection.py +0 -0
  51. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/exceptions.py +0 -0
  52. {redqueue-0.13.1 → redqueue-0.14.0}/src/redqueue/serialization.py +0 -0
  53. {redqueue-0.13.1 → redqueue-0.14.0}/tests/README.md +0 -0
  54. {redqueue-0.13.1 → redqueue-0.14.0}/tests/__init__.py +0 -0
  55. {redqueue-0.13.1 → redqueue-0.14.0}/tests/test_availability.py +0 -0
  56. {redqueue-0.13.1 → redqueue-0.14.0}/tests/test_backend_contracts.py +0 -0
  57. {redqueue-0.13.1 → redqueue-0.14.0}/tests/test_cli.py +0 -0
  58. {redqueue-0.13.1 → redqueue-0.14.0}/tests/test_integration_redis.py +0 -0
  59. {redqueue-0.13.1 → redqueue-0.14.0}/tests/test_performance.py +0 -0
  60. {redqueue-0.13.1 → redqueue-0.14.0}/tests/test_real_redis_performance.py +0 -0
@@ -7,26 +7,44 @@ All notable public release changes are documented here.
7
7
  Development versions are tracked separately from formal release versions.
8
8
  开发版本与正式版本分开管理。
9
9
 
10
- ## [0.13.1] - 2026-06-27
11
-
12
- ### Fixed
10
+ ## [0.14.0] - 2026-06-27
13
11
 
14
- - Fixed a compatibility regression where legacy messages with blank
15
- `headers["trace_id"]` values could fail to construct or consume after
16
- upgrading to `0.13.0`.
17
- - Fixed sync and async `publish(..., delay=..., message_id=...)` so delayed
18
- publishing preserves caller-provided message ids.
12
+ ### Added
19
13
 
20
- ### 修复
14
+ - Added opt-in Redis-backed message deduplication with
15
+ `DeduplicationConfig`.
16
+ - Added `dedup_key` support to sync and async `publish()` and `delay()`.
17
+ - Added duplicate-hit behavior that returns the first message id without
18
+ enqueueing or scheduling another message.
19
+ - Added `message.deduplicated` monitoring events.
21
20
 
22
- - 修复升级到 `0.13.0` 后,历史消息中空白 `headers["trace_id"]` 可能导致
23
- 消息构造或消费失败的兼容性回归。
24
- - 修复同步和异步 `publish(..., delay=..., message_id=...)`,现在延迟发布会
25
- 保留调用方传入的消息 ID。
21
+ ### 新增
26
22
 
27
- ## [0.13.0] - 2026-06-27
23
+ - 新增基于 Redis 的可选消息去重能力,通过 `DeduplicationConfig` 启用。
24
+ - 同步和异步 `publish()`、`delay()` 新增 `dedup_key` 参数。
25
+ - 重复命中时返回第一次消息 ID,不再重复入队或重复调度。
26
+ - 新增 `message.deduplicated` 监控事件。
28
27
 
29
- ### Added
28
+ ## [0.13.1] - 2026-06-27
29
+
30
+ ### Fixed
31
+
32
+ - Fixed a compatibility regression where legacy messages with blank
33
+ `headers["trace_id"]` values could fail to construct or consume after
34
+ upgrading to `0.13.0`.
35
+ - Fixed sync and async `publish(..., delay=..., message_id=...)` so delayed
36
+ publishing preserves caller-provided message ids.
37
+
38
+ ### 修复
39
+
40
+ - 修复升级到 `0.13.0` 后,历史消息中空白 `headers["trace_id"]` 可能导致
41
+ 消息构造或消费失败的兼容性回归。
42
+ - 修复同步和异步 `publish(..., delay=..., message_id=...)`,现在延迟发布会
43
+ 保留调用方传入的消息 ID。
44
+
45
+ ## [0.13.0] - 2026-06-27
46
+
47
+ ### Added
30
48
 
31
49
  - Added first-class `trace_id` support to `Message`, sync and async
32
50
  `publish()`, sync and async `delay()`, List, Streams, and delayed task
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redqueue
3
- Version: 0.13.1
4
- Summary: Redis-backed Python message queue library with List, Streams, delayed tasks, and monitoring.
3
+ Version: 0.14.0
4
+ Summary: Redis-backed Python message queue library with List, Streams, delayed tasks, deduplication, and monitoring.
5
5
  Project-URL: Homepage, https://github.com/SpringMirror-pear/redqueue
6
6
  Project-URL: Repository, https://github.com/SpringMirror-pear/redqueue.git
7
7
  Project-URL: Issues, https://github.com/SpringMirror-pear/redqueue/issues
@@ -52,6 +52,7 @@ https://github.com/SpringMirror-pear/redqueue.git
52
52
  - Redis connection pool managers for shared sync and async resources.
53
53
  - `redqueue` CLI for local debugging and operational checks.
54
54
  - First-class `trace_id` propagation for lifecycle tracing.
55
+ - Opt-in message deduplication with Redis `SET NX` and TTL windows.
55
56
  - Unified exception hierarchy with structured context.
56
57
  - Monitoring events for publish, consume, ack, nack, retry, dead letter, delay,
57
58
  and backend errors.
@@ -75,6 +76,7 @@ Redis:
75
76
  | Streams | `>=5.0` | Uses `XADD`, `XGROUP CREATE`, `XREADGROUP` |
76
77
  | Streams auto claim | `>=6.2` | Uses `XAUTOCLAIM`; Redis 5.x uses `XPENDING`/`XCLAIM` fallback |
77
78
  | Delayed tasks | `>=1.2` | Uses `ZADD` and timestamp scores |
79
+ | Message deduplication | `>=2.6.12` | Uses `SET` with `NX` and `EX`/`PX` |
78
80
 
79
81
  ## Installation
80
82
 
@@ -210,6 +212,23 @@ client.delay({"to": "later@example.com"}, delay_seconds=60, trace_id="trace-123"
210
212
  released = client.schedule_due(limit=100)
211
213
  ```
212
214
 
215
+ Message deduplication:
216
+
217
+ ```python
218
+ from redqueue import DeduplicationConfig, QueueClient
219
+
220
+ client = QueueClient.from_url(
221
+ "redis://127.0.0.1:6379/0",
222
+ queue="emails",
223
+ deduplication=DeduplicationConfig(enabled=True, ttl_seconds=3600),
224
+ )
225
+
226
+ first_id = client.publish({"order": 1}, dedup_key="order-1")
227
+ second_id = client.publish({"order": 1}, dedup_key="order-1")
228
+
229
+ assert second_id == first_id
230
+ ```
231
+
213
232
  Trace IDs:
214
233
 
215
234
  ```python
@@ -367,17 +386,21 @@ REDQUEUE_REDIS_URL=redis://127.0.0.1:6379/0 PYTHONPATH=src python -m pytest -m "
367
386
 
368
387
  Latest local run on Python `3.14.5`:
369
388
 
370
- - Full test suite without `REDQUEUE_REDIS_URL`: `102 passed, 8 skipped`.
371
- - Real Redis availability suite: `3 passed` with
389
+ - Full test suite without `REDQUEUE_REDIS_URL`: `114 passed, 10 skipped`.
390
+ - Real Redis integration suite: `10 passed` with
391
+ `redis://127.0.0.1:6379/0`.
392
+ - Real Redis availability suite: `5 passed` with
372
393
  `redis://127.0.0.1:6379/0`.
373
394
  - Real Redis server: Redis for Windows `5.0.14.1`.
374
395
  - Availability suite: covers List processing recovery, List dead-letter
375
396
  requeue, Streams Redis `<5.0` compatibility rejection, Streams Redis 5.x
376
397
  pending recovery fallback, Streams dead-letter requeue, delayed task publish
377
- failure rollback, missing delayed payload errors, async List recovery, async
378
- Streams dead-letter requeue, and async delayed task rollback.
398
+ failure rollback, missing delayed payload errors, publish-time deduplication,
399
+ delayed task deduplication, async List recovery, async Streams dead-letter
400
+ requeue, and async delayed task rollback.
379
401
  - Real Redis availability suite additionally validates List recovery, Streams
380
- dead-letter requeue, and delayed task rollback against a running Redis server.
402
+ dead-letter requeue, delayed task rollback, List deduplication, and delayed
403
+ task deduplication against a running Redis server.
381
404
 
382
405
  ## Performance Results
383
406
 
@@ -15,10 +15,11 @@ https://github.com/SpringMirror-pear/redqueue.git
15
15
  - 基于 Redis Streams 的消费组后端,Streams 要求 Redis `>=5.0`。
16
16
  - 基于 Redis Sorted Set 的延迟任务。
17
17
  - 同步客户端 `QueueClient` 与异步客户端 `AsyncQueueClient`。
18
- - 支持同步和异步 Redis 连接池管理器,方便多个客户端共享连接池。
19
- - 提供 `redqueue` CLI,用于本地调试和运行时检查。
20
- - 一等 `trace_id` 链路追踪能力,贯穿消息生命周期。
21
- - 带结构化上下文的统一异常体系。
18
+ - 支持同步和异步 Redis 连接池管理器,方便多个客户端共享连接池。
19
+ - 提供 `redqueue` CLI,用于本地调试和运行时检查。
20
+ - 一等 `trace_id` 链路追踪能力,贯穿消息生命周期。
21
+ - 可选消息去重能力,基于 Redis `SET NX` 和 TTL 窗口。
22
+ - 带结构化上下文的统一异常体系。
22
23
  - 针对发布、消费、确认、拒绝、重试、死信、延迟和后端错误的监控事件。
23
24
  - 通过 `INFO server` 探测 Redis 能力。
24
25
  - Apache License 2.0。
@@ -37,9 +38,10 @@ Redis:
37
38
  | --- | --- | --- |
38
39
  | List 阻塞消费 | `>=2.0` | 以 `BLPOP` 系列能力为基础 |
39
40
  | List 可靠搬移 | `>=2.2` | 使用 `BRPOPLPUSH`;Redis `>=6.2` 优先使用 `BLMOVE` |
40
- | Streams | `>=5.0` | 使用 `XADD`、`XGROUP CREATE`、`XREADGROUP` |
41
- | Streams 自动认领 | `>=6.2` | 使用 `XAUTOCLAIM`;Redis 5.x 回退 `XPENDING`/`XCLAIM` |
42
- | 延迟任务 | `>=1.2` | 使用 `ZADD` 和时间戳 score |
41
+ | Streams | `>=5.0` | 使用 `XADD`、`XGROUP CREATE`、`XREADGROUP` |
42
+ | Streams 自动认领 | `>=6.2` | 使用 `XAUTOCLAIM`;Redis 5.x 回退 `XPENDING`/`XCLAIM` |
43
+ | 延迟任务 | `>=1.2` | 使用 `ZADD` 和时间戳 score |
44
+ | 消息去重 | `>=2.6.12` | 使用带 `NX` 和 `EX`/`PX` 的 `SET` |
43
45
 
44
46
  ## 安装
45
47
 
@@ -165,17 +167,34 @@ async def main() -> None:
165
167
  asyncio.run(main())
166
168
  ```
167
169
 
168
- 延迟任务:
170
+ 延迟任务:
169
171
 
170
172
  ```python
171
173
  from redqueue import QueueClient
172
174
 
173
175
  client = QueueClient.from_url("redis://127.0.0.1:6379/0", queue="emails")
174
176
  client.delay({"to": "later@example.com"}, delay_seconds=60, trace_id="trace-123")
175
- released = client.schedule_due(limit=100)
176
- ```
177
-
178
- 链路追踪:
177
+ released = client.schedule_due(limit=100)
178
+ ```
179
+
180
+ 消息去重:
181
+
182
+ ```python
183
+ from redqueue import DeduplicationConfig, QueueClient
184
+
185
+ client = QueueClient.from_url(
186
+ "redis://127.0.0.1:6379/0",
187
+ queue="emails",
188
+ deduplication=DeduplicationConfig(enabled=True, ttl_seconds=3600),
189
+ )
190
+
191
+ first_id = client.publish({"order": 1}, dedup_key="order-1")
192
+ second_id = client.publish({"order": 1}, dedup_key="order-1")
193
+
194
+ assert second_id == first_id
195
+ ```
196
+
197
+ 链路追踪:
179
198
 
180
199
  ```python
181
200
  from redqueue import InMemoryMonitoringHook, QueueClient, new_trace_id
@@ -329,15 +348,16 @@ REDQUEUE_REDIS_URL=redis://127.0.0.1:6379/0 PYTHONPATH=src python -m pytest -m "
329
348
 
330
349
  Python `3.14.5` 最新本地运行结果:
331
350
 
332
- - 未设置 `REDQUEUE_REDIS_URL` 时的完整测试套件:`102 passed, 8 skipped`。
333
- - 真实 Redis 可用性套件:使用 `redis://127.0.0.1:6379/0` 时 `3 passed`。
351
+ - 未设置 `REDQUEUE_REDIS_URL` 时的完整测试套件:`114 passed, 10 skipped`。
352
+ - 真实 Redis 集成套件:使用 `redis://127.0.0.1:6379/0` 时 `10 passed`。
353
+ - 真实 Redis 可用性套件:使用 `redis://127.0.0.1:6379/0` 时 `5 passed`。
334
354
  - 真实 Redis 服务端:Redis for Windows `5.0.14.1`。
335
355
  - 可用性套件覆盖:List processing 恢复、List 死信重放、Streams Redis
336
356
  `<5.0` 兼容性拒绝、Streams Redis 5.x pending 恢复回退、Streams 死信
337
- 重放、延迟任务发布失败回滚、延迟 payload 缺失错误、异步 List 恢复、异步
338
- Streams 死信重放和异步延迟任务回滚。
339
- - 真实 Redis 可用性套件额外验证了运行中 Redis 服务上的 List 恢复、Streams
340
- 死信重放和延迟任务回滚。
357
+ 重放、延迟任务发布失败回滚、延迟 payload 缺失错误、发布时去重、延迟任务
358
+ 去重、异步 List 恢复、异步 Streams 死信重放和异步延迟任务回滚。
359
+ - 真实 Redis 可用性套件额外验证了运行中 Redis 服务上的 List 恢复、Streams
360
+ 死信重放、延迟任务回滚、List 去重和延迟任务去重。
341
361
 
342
362
  ## 性能测试结果
343
363
 
@@ -16,10 +16,11 @@ https://github.com/SpringMirror-pear/redqueue.git
16
16
  - Redis Streams backend with consumer groups. Streams require Redis `>=5.0`.
17
17
  - Delayed tasks based on Redis Sorted Set.
18
18
  - Sync client `QueueClient` and async client `AsyncQueueClient`.
19
- - Redis connection pool managers for shared sync and async resources.
20
- - `redqueue` CLI for local debugging and operational checks.
21
- - First-class `trace_id` propagation for lifecycle tracing.
22
- - Unified exception hierarchy with structured context.
19
+ - Redis connection pool managers for shared sync and async resources.
20
+ - `redqueue` CLI for local debugging and operational checks.
21
+ - First-class `trace_id` propagation for lifecycle tracing.
22
+ - Opt-in message deduplication with Redis `SET NX` and TTL windows.
23
+ - Unified exception hierarchy with structured context.
23
24
  - Monitoring events for publish, consume, ack, nack, retry, dead letter, delay,
24
25
  and backend errors.
25
26
  - Redis capability detection from `INFO server`.
@@ -39,9 +40,10 @@ Redis:
39
40
  | --- | --- | --- |
40
41
  | List blocking consume | `>=2.0` | Uses `BLPOP` family compatibility baseline |
41
42
  | List reliable move | `>=2.2` | Uses `BRPOPLPUSH`; `BLMOVE` preferred on `>=6.2` |
42
- | Streams | `>=5.0` | Uses `XADD`, `XGROUP CREATE`, `XREADGROUP` |
43
- | Streams auto claim | `>=6.2` | Uses `XAUTOCLAIM`; Redis 5.x uses `XPENDING`/`XCLAIM` fallback |
44
- | Delayed tasks | `>=1.2` | Uses `ZADD` and timestamp scores |
43
+ | Streams | `>=5.0` | Uses `XADD`, `XGROUP CREATE`, `XREADGROUP` |
44
+ | Streams auto claim | `>=6.2` | Uses `XAUTOCLAIM`; Redis 5.x uses `XPENDING`/`XCLAIM` fallback |
45
+ | Delayed tasks | `>=1.2` | Uses `ZADD` and timestamp scores |
46
+ | Message deduplication | `>=2.6.12` | Uses `SET` with `NX` and `EX`/`PX` |
45
47
 
46
48
  ## Installation
47
49
 
@@ -167,17 +169,34 @@ async def main() -> None:
167
169
  asyncio.run(main())
168
170
  ```
169
171
 
170
- Delayed task:
172
+ Delayed task:
171
173
 
172
174
  ```python
173
175
  from redqueue import QueueClient
174
176
 
175
177
  client = QueueClient.from_url("redis://127.0.0.1:6379/0", queue="emails")
176
178
  client.delay({"to": "later@example.com"}, delay_seconds=60, trace_id="trace-123")
177
- released = client.schedule_due(limit=100)
178
- ```
179
-
180
- Trace IDs:
179
+ released = client.schedule_due(limit=100)
180
+ ```
181
+
182
+ Message deduplication:
183
+
184
+ ```python
185
+ from redqueue import DeduplicationConfig, QueueClient
186
+
187
+ client = QueueClient.from_url(
188
+ "redis://127.0.0.1:6379/0",
189
+ queue="emails",
190
+ deduplication=DeduplicationConfig(enabled=True, ttl_seconds=3600),
191
+ )
192
+
193
+ first_id = client.publish({"order": 1}, dedup_key="order-1")
194
+ second_id = client.publish({"order": 1}, dedup_key="order-1")
195
+
196
+ assert second_id == first_id
197
+ ```
198
+
199
+ Trace IDs:
181
200
 
182
201
  ```python
183
202
  from redqueue import InMemoryMonitoringHook, QueueClient, new_trace_id
@@ -334,17 +353,21 @@ REDQUEUE_REDIS_URL=redis://127.0.0.1:6379/0 PYTHONPATH=src python -m pytest -m "
334
353
 
335
354
  Latest local run on Python `3.14.5`:
336
355
 
337
- - Full test suite without `REDQUEUE_REDIS_URL`: `102 passed, 8 skipped`.
338
- - Real Redis availability suite: `3 passed` with
339
- `redis://127.0.0.1:6379/0`.
356
+ - Full test suite without `REDQUEUE_REDIS_URL`: `114 passed, 10 skipped`.
357
+ - Real Redis integration suite: `10 passed` with
358
+ `redis://127.0.0.1:6379/0`.
359
+ - Real Redis availability suite: `5 passed` with
360
+ `redis://127.0.0.1:6379/0`.
340
361
  - Real Redis server: Redis for Windows `5.0.14.1`.
341
362
  - Availability suite: covers List processing recovery, List dead-letter
342
363
  requeue, Streams Redis `<5.0` compatibility rejection, Streams Redis 5.x
343
364
  pending recovery fallback, Streams dead-letter requeue, delayed task publish
344
- failure rollback, missing delayed payload errors, async List recovery, async
345
- Streams dead-letter requeue, and async delayed task rollback.
346
- - Real Redis availability suite additionally validates List recovery, Streams
347
- dead-letter requeue, and delayed task rollback against a running Redis server.
365
+ failure rollback, missing delayed payload errors, publish-time deduplication,
366
+ delayed task deduplication, async List recovery, async Streams dead-letter
367
+ requeue, and async delayed task rollback.
368
+ - Real Redis availability suite additionally validates List recovery, Streams
369
+ dead-letter requeue, delayed task rollback, List deduplication, and delayed
370
+ task deduplication against a running Redis server.
348
371
 
349
372
  ## Performance Results
350
373
 
@@ -1,8 +1,8 @@
1
1
  # RedQueue API / RedQueue API 文档
2
2
 
3
- This document describes the public API available in RedQueue `0.13.1`.
3
+ This document describes the public API available in RedQueue `0.14.0`.
4
4
 
5
- 本文档描述 RedQueue `0.13.1` 的公开 API。
5
+ 本文档描述 RedQueue `0.14.0` 的公开 API。
6
6
 
7
7
  ## Clients / 客户端
8
8
 
@@ -27,12 +27,12 @@ Methods / 方法:
27
27
  - `from_url(url, *, queue, backend="list", connection_manager=None, **options) -> QueueClient`
28
28
  - Advanced options include `pool_options`, injected `redis`, injected
29
29
  `capabilities`, and `owns_redis`.
30
- - `publish(payload, *, delay=None, headers=None, message_id=None, trace_id=None) -> str`
30
+ - `publish(payload, *, delay=None, headers=None, message_id=None, trace_id=None, dedup_key=None) -> str`
31
31
  - `consume(*, timeout=None, batch_size=1) -> Message | list[Message] | None`
32
32
  - `ack(message) -> None`
33
33
  - `nack(message, *, requeue=True) -> None`
34
34
  - `retry(message, *, delay=None, reason=None) -> None`
35
- - `delay(payload, *, delay_seconds=None, run_at=None, headers=None, message_id=None, trace_id=None) -> str`
35
+ - `delay(payload, *, delay_seconds=None, run_at=None, headers=None, message_id=None, trace_id=None, dedup_key=None) -> str`
36
36
  - `schedule_due(*, limit=100, now=None) -> int`
37
37
  - `recover_stale(*, min_idle_ms=None, limit=100) -> int`
38
38
  - `dead_letters(*, limit=100) -> list[Message]`
@@ -61,12 +61,12 @@ Methods / 方法:
61
61
  - `await from_url(url, *, queue, backend="list", connection_manager=None, **options) -> AsyncQueueClient`
62
62
  - Advanced options include `pool_options`, injected `redis`, injected
63
63
  `capabilities`, and `owns_redis`.
64
- - `await publish(payload, *, delay=None, headers=None, message_id=None, trace_id=None) -> str`
64
+ - `await publish(payload, *, delay=None, headers=None, message_id=None, trace_id=None, dedup_key=None) -> str`
65
65
  - `await consume(*, timeout=None, batch_size=1) -> Message | list[Message] | None`
66
66
  - `await ack(message) -> None`
67
67
  - `await nack(message, *, requeue=True) -> None`
68
68
  - `await retry(message, *, delay=None, reason=None) -> None`
69
- - `await delay(payload, *, delay_seconds=None, run_at=None, headers=None, message_id=None, trace_id=None) -> str`
69
+ - `await delay(payload, *, delay_seconds=None, run_at=None, headers=None, message_id=None, trace_id=None, dedup_key=None) -> str`
70
70
  - `await schedule_due(*, limit=100, now=None) -> int`
71
71
  - `await recover_stale(*, min_idle_ms=None, limit=100) -> int`
72
72
  - `await dead_letters(*, limit=100) -> list[Message]`
@@ -147,9 +147,10 @@ Important fields / 重要字段:
147
147
  - `queue: str`
148
148
  - `backend: BackendType | str = BackendType.LIST`
149
149
  - `enable_delay: bool = False`
150
- - `namespace: str = "rq"`
151
- - `retry: RetryConfig`
152
- - `monitoring: MonitoringHook`
150
+ - `namespace: str = "rq"`
151
+ - `retry: RetryConfig`
152
+ - `deduplication: DeduplicationConfig`
153
+ - `monitoring: MonitoringHook`
153
154
  - `serializer: Serializer`
154
155
  - `visibility_timeout_seconds: float = 300.0`
155
156
  - `consumer_group: str = "redqueue"`
@@ -165,9 +166,44 @@ Retry policy for failed messages.
165
166
  - `max_retries: int = 3`
166
167
  - `base_delay_seconds: float = 0.0`
167
168
  - `max_delay_seconds: float | None = None`
168
- - `next_delay(attempts: int) -> float`
169
-
170
- ### `BackendType`
169
+ - `next_delay(attempts: int) -> float`
170
+
171
+ ### `DeduplicationConfig`
172
+
173
+ Opt-in publish-time deduplication window.
174
+
175
+ 可选的发布时去重窗口配置。
176
+
177
+ - `enabled: bool = False`
178
+ - `ttl_seconds: float = 86400.0`
179
+
180
+ When enabled, callers may pass `dedup_key` to `publish()` or `delay()`. RedQueue
181
+ stores the first message id in Redis with `SET NX` and the configured TTL.
182
+ Duplicate calls with the same key return the stored message id and do not
183
+ enqueue or schedule another message. Deduplication keys are not deleted on
184
+ `ack()`; the TTL controls the deduplication window.
185
+
186
+ 启用后,调用方可以在 `publish()` 或 `delay()` 中传入 `dedup_key`。RedQueue
187
+ 会用 Redis `SET NX` 和配置的 TTL 存储第一次消息 ID。相同 key 的重复调用会
188
+ 返回已存储的消息 ID,不会再次入队或调度。去重 key 不会在 `ack()` 时删除;
189
+ TTL 控制去重窗口。
190
+
191
+ ```python
192
+ from redqueue import DeduplicationConfig, QueueClient
193
+
194
+ client = QueueClient.from_url(
195
+ "redis://127.0.0.1:6379/0",
196
+ queue="emails",
197
+ deduplication=DeduplicationConfig(enabled=True, ttl_seconds=3600),
198
+ )
199
+
200
+ first_id = client.publish({"order": 1}, dedup_key="order-1")
201
+ second_id = client.publish({"order": 1}, dedup_key="order-1")
202
+
203
+ assert second_id == first_id
204
+ ```
205
+
206
+ ### `BackendType`
171
207
 
172
208
  Supported backends.
173
209
 
@@ -309,9 +345,10 @@ All RedQueue custom exceptions inherit from `RedQueueError`.
309
345
  - `message.consumed`
310
346
  - `message.acked`
311
347
  - `message.nacked`
312
- - `message.retried`
313
- - `message.dead_lettered`
314
- - `delay.scheduled`
348
+ - `message.retried`
349
+ - `message.dead_lettered`
350
+ - `message.deduplicated`
351
+ - `delay.scheduled`
315
352
  - `delay.released`
316
353
  - `backend.error`
317
354
 
@@ -345,10 +382,10 @@ Streams are rejected with `RedisCompatibilityError` when Redis is below `5.0`.
345
382
 
346
383
  ## CLI / 命令行工具
347
384
 
348
- RedQueue `0.13.1` provides a `redqueue` console command and a
385
+ RedQueue `0.14.0` provides a `redqueue` console command and a
349
386
  `python -m redqueue` module entry point for developer diagnostics.
350
387
 
351
- RedQueue `0.13.1` 提供 `redqueue` 控制台命令和 `python -m redqueue`
388
+ RedQueue `0.14.0` 提供 `redqueue` 控制台命令和 `python -m redqueue`
352
389
  模块入口,用于开发者调试。
353
390
 
354
391
  Commands / 命令: