queue-func 0.1__tar.gz → 0.1.2__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 (49) hide show
  1. queue_func-0.1.2/PKG-INFO +183 -0
  2. queue_func-0.1.2/README.md +158 -0
  3. {queue_func-0.1 → queue_func-0.1.2}/pyproject.toml +8 -1
  4. queue_func-0.1.2/queue_func/__init__.py +7 -0
  5. {queue_func-0.1 → queue_func-0.1.2}/queue_func/broker/base.py +12 -14
  6. {queue_func-0.1 → queue_func-0.1.2}/queue_func/broker/queue.py +7 -7
  7. {queue_func-0.1 → queue_func-0.1.2}/queue_func/config/general.py +2 -6
  8. {queue_func-0.1 → queue_func-0.1.2}/queue_func/config/queue.py +3 -0
  9. {queue_func-0.1 → queue_func-0.1.2}/queue_func/consumer/base.py +5 -5
  10. {queue_func-0.1 → queue_func-0.1.2}/queue_func/consumer/queue.py +7 -7
  11. queue_func-0.1.2/queue_func/errors.py +7 -0
  12. {queue_func-0.1 → queue_func-0.1.2}/queue_func/factory/deco.py +4 -6
  13. queue_func-0.1.2/queue_func/producer/base.py +44 -0
  14. queue_func-0.1.2/queue_func/producer/queue.py +32 -0
  15. queue_func-0.1.2/queue_func/serializer/base.py +27 -0
  16. queue_func-0.1.2/queue_func/serializer/orjson_ser.py +27 -0
  17. queue_func-0.1.2/queue_func/serializer/raw.py +24 -0
  18. queue_func-0.1/PKG-INFO +0 -121
  19. queue_func-0.1/README.md +0 -101
  20. queue_func-0.1/queue_func/message/base.py +0 -39
  21. queue_func-0.1/queue_func/message/general.py +0 -30
  22. queue_func-0.1/queue_func/producer/base.py +0 -36
  23. queue_func-0.1/queue_func/producer/queue.py +0 -30
  24. queue_func-0.1/queue_func/serializer/__init__.py +0 -1
  25. queue_func-0.1/queue_func/serializer/base.py +0 -38
  26. queue_func-0.1/queue_func/serializer/json_ser.py +0 -25
  27. queue_func-0.1/queue_func/serializer/orjson_ser.py +0 -30
  28. queue_func-0.1/queue_func/serializer/utils.py +0 -16
  29. queue_func-0.1/queue_func/task/__init__.py +0 -1
  30. {queue_func-0.1 → queue_func-0.1.2}/LICENSE +0 -0
  31. {queue_func-0.1/queue_func → queue_func-0.1.2/queue_func/broker}/__init__.py +0 -0
  32. {queue_func-0.1/queue_func/broker → queue_func-0.1.2/queue_func/config}/__init__.py +0 -0
  33. {queue_func-0.1 → queue_func-0.1.2}/queue_func/config/utils.py +0 -0
  34. {queue_func-0.1/queue_func/config → queue_func-0.1.2/queue_func/consumer}/__init__.py +0 -0
  35. {queue_func-0.1 → queue_func-0.1.2}/queue_func/factory/__init__.py +0 -0
  36. {queue_func-0.1 → queue_func-0.1.2}/queue_func/factory/backend.py +0 -0
  37. {queue_func-0.1 → queue_func-0.1.2}/queue_func/factory/builders/__init__.py +0 -0
  38. {queue_func-0.1 → queue_func-0.1.2}/queue_func/factory/builders/queue.py +0 -0
  39. {queue_func-0.1 → queue_func-0.1.2}/queue_func/factory/registry.py +0 -0
  40. {queue_func-0.1 → queue_func-0.1.2}/queue_func/factory/runtime.py +0 -0
  41. {queue_func-0.1/queue_func/consumer → queue_func-0.1.2/queue_func/pool_executor}/__init__.py +0 -0
  42. {queue_func-0.1 → queue_func-0.1.2}/queue_func/pool_executor/base.py +0 -0
  43. {queue_func-0.1 → queue_func-0.1.2}/queue_func/pool_executor/general.py +0 -0
  44. {queue_func-0.1 → queue_func-0.1.2}/queue_func/pool_executor/utils.py +0 -0
  45. {queue_func-0.1/queue_func/message → queue_func-0.1.2/queue_func/producer}/__init__.py +0 -0
  46. {queue_func-0.1/queue_func/pool_executor → queue_func-0.1.2/queue_func/serializer}/__init__.py +0 -0
  47. {queue_func-0.1/queue_func/producer → queue_func-0.1.2/queue_func/task}/__init__.py +0 -0
  48. {queue_func-0.1 → queue_func-0.1.2}/queue_func/task/base.py +0 -0
  49. {queue_func-0.1 → queue_func-0.1.2}/queue_func/task/thread.py +0 -0
@@ -0,0 +1,183 @@
1
+ Metadata-Version: 2.4
2
+ Name: queue-func
3
+ Version: 0.1.2
4
+ Summary: Async coroutine functions as queue-backed tasks (QueueFunc).
5
+ License: Apache-2.0
6
+ License-File: LICENSE
7
+ Author: liuseki
8
+ Author-email: liuseki@163.com
9
+ Requires-Python: >=3.12,<4.0
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Programming Language :: Python :: 3.15
16
+ Requires-Dist: orjson
17
+ Requires-Dist: pydantic (>=2.14.1,<3.0.0)
18
+ Project-URL: Changelog, https://github.com/sekil9529/queue-func/blob/master/Changelog.rst
19
+ Project-URL: Documentation, https://github.com/sekil9529/queue-func#readme
20
+ Project-URL: Homepage, https://github.com/sekil9529/queue-func
21
+ Project-URL: Issues, https://github.com/sekil9529/queue-func/issues
22
+ Project-URL: Repository, https://github.com/sekil9529/queue-func
23
+ Description-Content-Type: text/markdown
24
+
25
+ # queue-func
26
+
27
+ 把 **`async def` 协程** 变成可 **`push`** 的队列任务:在 asyncio 里投递、消费,并按通道控制并发与背压。
28
+
29
+ 需要 **Python 3.12+**;任务入口必须是协程,不支持普通 `def`。
30
+
31
+ 仓库:[github.com/sekil9529/queue-func](https://github.com/sekil9529/queue-func)
32
+
33
+ ## 特点
34
+
35
+ - **asyncio 原生**:consumer 在同一事件循环里池化 `await` 任务,与 FastAPI / Starlette 等同进程组合很自然。
36
+ - **运行时聚焦队列链路**:`pack` → 投递 → `unpack` → 执行;生命周期由 `broker` / `QueueFuncRuntime` 显式管理。
37
+ - **环节可扩展**:通过 `register_backend` 接入新队列;`Serializer.pack` / `unpack` 决定队列里的数据结构。
38
+ - **每个 `QueueFunc` 独立消费并发**:各自 `consumer_pool_maxsize`。一个进程里可用 `QueueFuncRuntime` 同时跑多段流水线(例如 count → list → detail),**各段并发互不影响**。
39
+
40
+ ## 架构设计
41
+
42
+ ### Func
43
+
44
+ 业务协程:一个 `async def`,用 `@queue` 装饰。
45
+
46
+ ### Queue
47
+
48
+ 装饰之后,这个 Func 就是一条队列,`push` 投到它自己这条队列上。
49
+
50
+ ### Broker
51
+
52
+ 组装 Producer、Consumer 的公有对象,提供对外接口。
53
+
54
+ ### Serializer
55
+
56
+ 控制队列中的数据结构:`pack` 写入,`unpack` 读出后还原成 `(args, kwargs)`。
57
+
58
+ - `raw.Serializer`:队列中保持 `(args, kwargs)`。
59
+ - `orjson_ser.Serializer`:队列中是 `bytes`。
60
+
61
+ ### Producer
62
+
63
+ 调用 `Serializer.pack` 后把数据写入队列。
64
+
65
+ ### Consumer
66
+
67
+ 从队列得到数据,`Serializer.unpack` 后交给 PoolExecutor 执行。
68
+
69
+ ### PoolExecutor
70
+
71
+ 按并发上限执行业务协程。
72
+
73
+
74
+
75
+ ### 组件关系
76
+
77
+ ```mermaid
78
+ flowchart TB
79
+ PUSH["push"] --> B["Broker"]
80
+ B --> PRO["Producer"]
81
+ B -.->|启停| CON["Consumer"]
82
+
83
+ PRO -->|Serializer.pack| Q[("QUEUE")]
84
+ Q -->|Serializer.unpack| CON
85
+ CON --> POOL["PoolExecutor"]
86
+ POOL --> FN["async def"]
87
+ ```
88
+
89
+ ## 当前实现
90
+
91
+ | Backend | 说明 |
92
+ |---------|------|
93
+ | **`Backend.QUEUE`** | 进程内 `asyncio.Queue`(已可用) |
94
+ | RabbitMQ、Kafka 等 | 通过同一套 Broker / Producer / Consumer 扩展点接入(见 [Changelog.rst](Changelog.rst)) |
95
+
96
+ 接入 MQ 后端后,producer / consumer 可部署在不同进程或机器;**现阶段发行版仅包含内存队列实现**。
97
+
98
+ ## 快速开始
99
+
100
+ 安装(开发):
101
+
102
+ ```bash
103
+ git clone https://github.com/sekil9529/queue-func.git
104
+ cd queue-func
105
+ poetry install
106
+ ```
107
+
108
+ 单个 `QueueFunc`:
109
+
110
+ ```python
111
+ import asyncio
112
+
113
+ from queue_func.factory import Backend, queue
114
+
115
+
116
+ @queue(Backend.QUEUE, consume_timeout=0.5, maxsize=1000)
117
+ async def process_order(order_id: int):
118
+ ...
119
+
120
+
121
+ async def main():
122
+ await process_order.broker.start_consumer()
123
+ await process_order.push(args=(42,))
124
+ await process_order.broker.stop_consumer()
125
+ await process_order.broker.join_consumer()
126
+
127
+
128
+ asyncio.run(main())
129
+ ```
130
+
131
+ - `push` 等价于 `broker.publish`。不传 `timeout` 时用 `publish_timeout`;传入数字只改这一次。`None` 表示不限时。超时抛出 `queue_func.PublishTimeoutError`
132
+ - 仍可直接 `await process_order(1)`,不经过队列
133
+
134
+ 多段流水线(各段独立队列与并发上限):
135
+
136
+ ```python
137
+ from queue_func.factory import Backend, QueueFuncRuntime, queue
138
+
139
+ # task_count 内 await task_list.push(...),task_list 内 await task_detail.push(...)
140
+
141
+
142
+ async def main():
143
+ runtime = QueueFuncRuntime([task_count, task_list, task_detail])
144
+ await runtime.start() # 按列表反序启动 consumer,下游先就绪
145
+ await task_count.push(args=(...,))
146
+ await runtime.stop()
147
+ ```
148
+
149
+ 链式示例(含日志):
150
+
151
+ ```bash
152
+ poetry run python examples/demo_queue.py
153
+ ```
154
+
155
+ 常用配置:`maxsize` / `publish_timeout`(队列背压与投递等待)、`consumer_pool_maxsize`(同时执行的协程数)、`serializer_cls`(队列中的数据结构)。低级组装见 `queue_func.config.queue.Config` 与 `queue_func.broker.queue.Broker`。
156
+
157
+ ## 项目结构
158
+
159
+ ```
160
+ queue_func/
161
+ ├── broker/
162
+ ├── producer/
163
+ ├── consumer/
164
+ ├── serializer/ # raw、orjson
165
+ ├── config/
166
+ ├── factory/ # @queue、QueueFunc、QueueFuncRuntime
167
+ └── pool_executor/
168
+ examples/
169
+ └── demo_queue.py
170
+ ```
171
+
172
+ ## 开发与测试
173
+
174
+ 版本与路线图:[Changelog.rst](Changelog.rst)
175
+
176
+ ```bash
177
+ pytest tests/ -q
178
+ ```
179
+
180
+ ## 许可证
181
+
182
+ Apache-2.0
183
+
@@ -0,0 +1,158 @@
1
+ # queue-func
2
+
3
+ 把 **`async def` 协程** 变成可 **`push`** 的队列任务:在 asyncio 里投递、消费,并按通道控制并发与背压。
4
+
5
+ 需要 **Python 3.12+**;任务入口必须是协程,不支持普通 `def`。
6
+
7
+ 仓库:[github.com/sekil9529/queue-func](https://github.com/sekil9529/queue-func)
8
+
9
+ ## 特点
10
+
11
+ - **asyncio 原生**:consumer 在同一事件循环里池化 `await` 任务,与 FastAPI / Starlette 等同进程组合很自然。
12
+ - **运行时聚焦队列链路**:`pack` → 投递 → `unpack` → 执行;生命周期由 `broker` / `QueueFuncRuntime` 显式管理。
13
+ - **环节可扩展**:通过 `register_backend` 接入新队列;`Serializer.pack` / `unpack` 决定队列里的数据结构。
14
+ - **每个 `QueueFunc` 独立消费并发**:各自 `consumer_pool_maxsize`。一个进程里可用 `QueueFuncRuntime` 同时跑多段流水线(例如 count → list → detail),**各段并发互不影响**。
15
+
16
+ ## 架构设计
17
+
18
+ ### Func
19
+
20
+ 业务协程:一个 `async def`,用 `@queue` 装饰。
21
+
22
+ ### Queue
23
+
24
+ 装饰之后,这个 Func 就是一条队列,`push` 投到它自己这条队列上。
25
+
26
+ ### Broker
27
+
28
+ 组装 Producer、Consumer 的公有对象,提供对外接口。
29
+
30
+ ### Serializer
31
+
32
+ 控制队列中的数据结构:`pack` 写入,`unpack` 读出后还原成 `(args, kwargs)`。
33
+
34
+ - `raw.Serializer`:队列中保持 `(args, kwargs)`。
35
+ - `orjson_ser.Serializer`:队列中是 `bytes`。
36
+
37
+ ### Producer
38
+
39
+ 调用 `Serializer.pack` 后把数据写入队列。
40
+
41
+ ### Consumer
42
+
43
+ 从队列得到数据,`Serializer.unpack` 后交给 PoolExecutor 执行。
44
+
45
+ ### PoolExecutor
46
+
47
+ 按并发上限执行业务协程。
48
+
49
+
50
+
51
+ ### 组件关系
52
+
53
+ ```mermaid
54
+ flowchart TB
55
+ PUSH["push"] --> B["Broker"]
56
+ B --> PRO["Producer"]
57
+ B -.->|启停| CON["Consumer"]
58
+
59
+ PRO -->|Serializer.pack| Q[("QUEUE")]
60
+ Q -->|Serializer.unpack| CON
61
+ CON --> POOL["PoolExecutor"]
62
+ POOL --> FN["async def"]
63
+ ```
64
+
65
+ ## 当前实现
66
+
67
+ | Backend | 说明 |
68
+ |---------|------|
69
+ | **`Backend.QUEUE`** | 进程内 `asyncio.Queue`(已可用) |
70
+ | RabbitMQ、Kafka 等 | 通过同一套 Broker / Producer / Consumer 扩展点接入(见 [Changelog.rst](Changelog.rst)) |
71
+
72
+ 接入 MQ 后端后,producer / consumer 可部署在不同进程或机器;**现阶段发行版仅包含内存队列实现**。
73
+
74
+ ## 快速开始
75
+
76
+ 安装(开发):
77
+
78
+ ```bash
79
+ git clone https://github.com/sekil9529/queue-func.git
80
+ cd queue-func
81
+ poetry install
82
+ ```
83
+
84
+ 单个 `QueueFunc`:
85
+
86
+ ```python
87
+ import asyncio
88
+
89
+ from queue_func.factory import Backend, queue
90
+
91
+
92
+ @queue(Backend.QUEUE, consume_timeout=0.5, maxsize=1000)
93
+ async def process_order(order_id: int):
94
+ ...
95
+
96
+
97
+ async def main():
98
+ await process_order.broker.start_consumer()
99
+ await process_order.push(args=(42,))
100
+ await process_order.broker.stop_consumer()
101
+ await process_order.broker.join_consumer()
102
+
103
+
104
+ asyncio.run(main())
105
+ ```
106
+
107
+ - `push` 等价于 `broker.publish`。不传 `timeout` 时用 `publish_timeout`;传入数字只改这一次。`None` 表示不限时。超时抛出 `queue_func.PublishTimeoutError`
108
+ - 仍可直接 `await process_order(1)`,不经过队列
109
+
110
+ 多段流水线(各段独立队列与并发上限):
111
+
112
+ ```python
113
+ from queue_func.factory import Backend, QueueFuncRuntime, queue
114
+
115
+ # task_count 内 await task_list.push(...),task_list 内 await task_detail.push(...)
116
+
117
+
118
+ async def main():
119
+ runtime = QueueFuncRuntime([task_count, task_list, task_detail])
120
+ await runtime.start() # 按列表反序启动 consumer,下游先就绪
121
+ await task_count.push(args=(...,))
122
+ await runtime.stop()
123
+ ```
124
+
125
+ 链式示例(含日志):
126
+
127
+ ```bash
128
+ poetry run python examples/demo_queue.py
129
+ ```
130
+
131
+ 常用配置:`maxsize` / `publish_timeout`(队列背压与投递等待)、`consumer_pool_maxsize`(同时执行的协程数)、`serializer_cls`(队列中的数据结构)。低级组装见 `queue_func.config.queue.Config` 与 `queue_func.broker.queue.Broker`。
132
+
133
+ ## 项目结构
134
+
135
+ ```
136
+ queue_func/
137
+ ├── broker/
138
+ ├── producer/
139
+ ├── consumer/
140
+ ├── serializer/ # raw、orjson
141
+ ├── config/
142
+ ├── factory/ # @queue、QueueFunc、QueueFuncRuntime
143
+ └── pool_executor/
144
+ examples/
145
+ └── demo_queue.py
146
+ ```
147
+
148
+ ## 开发与测试
149
+
150
+ 版本与路线图:[Changelog.rst](Changelog.rst)
151
+
152
+ ```bash
153
+ pytest tests/ -q
154
+ ```
155
+
156
+ ## 许可证
157
+
158
+ Apache-2.0
@@ -1,12 +1,19 @@
1
1
  [tool.poetry]
2
2
  name = "queue-func"
3
- version = "0.1"
3
+ version = "0.1.2"
4
4
  description = "Async coroutine functions as queue-backed tasks (QueueFunc)."
5
5
  authors = ["liuseki <liuseki@163.com>"]
6
6
  license = "Apache-2.0"
7
7
  readme = "README.md"
8
+ homepage = "https://github.com/sekil9529/queue-func"
9
+ repository = "https://github.com/sekil9529/queue-func"
10
+ documentation = "https://github.com/sekil9529/queue-func#readme"
8
11
  packages = [{ include = "queue_func" }]
9
12
 
13
+ [tool.poetry.urls]
14
+ Changelog = "https://github.com/sekil9529/queue-func/blob/master/Changelog.rst"
15
+ Issues = "https://github.com/sekil9529/queue-func/issues"
16
+
10
17
  [tool.poetry.dependencies]
11
18
  python = "^3.12"
12
19
  orjson = "*"
@@ -0,0 +1,7 @@
1
+ # coding: utf-8
2
+
3
+ from queue_func.errors import PublishTimeoutError
4
+
5
+ __all__ = (
6
+ "PublishTimeoutError",
7
+ )
@@ -3,7 +3,7 @@
3
3
  import abc
4
4
  import typing as t
5
5
 
6
- from queue_func.message.base import BaseMessage, Packed
6
+ from queue_func.serializer.base import BaseSerializer, Message
7
7
 
8
8
  if t.TYPE_CHECKING:
9
9
  from queue_func.config.general import Config
@@ -14,16 +14,16 @@ if t.TYPE_CHECKING:
14
14
  ConfigType = t.TypeVar("ConfigType", bound="Config")
15
15
 
16
16
 
17
- class BaseBroker(t.Generic[ConfigType, Packed], metaclass=abc.ABCMeta):
17
+ class BaseBroker(t.Generic[ConfigType, Message], metaclass=abc.ABCMeta):
18
18
  """一条通道的装配者。
19
19
 
20
- 创建时准备好双方共用的 Message,并持有配置与 Producer/Consumer。
20
+ 创建时准备好双方共用的 Serializer,并持有配置与 Producer/Consumer。
21
21
  对外通过 publish、start_consumer 等入口操作;运行期业务逻辑仍在 Producer/Consumer 内完成。
22
22
  """
23
23
 
24
24
  __slots__ = (
25
25
  "_config",
26
- "_message",
26
+ "_serializer",
27
27
  "_producer",
28
28
  "_consumer",
29
29
  )
@@ -31,35 +31,33 @@ class BaseBroker(t.Generic[ConfigType, Packed], metaclass=abc.ABCMeta):
31
31
  def __init__(self, config: ConfigType):
32
32
 
33
33
  self._config = config
34
- self._message: BaseMessage[Packed] = self._config.message_cls(
35
- message_serializer_cls=self._config.message_serializer_cls,
36
- enable_serializer=self._config.enable_message_serializer,
37
- )
34
+ self._serializer: type[BaseSerializer[Message]] = self._config.serializer_cls
38
35
  self._producer = self._create_producer()
39
36
  self._consumer = self._create_consumer()
40
37
 
41
38
  @abc.abstractmethod
42
- def _create_producer(self) -> "BaseProducer[Packed]":
39
+ def _create_producer(self) -> "BaseProducer[Message]":
43
40
 
44
41
  pass
45
42
 
46
43
  @abc.abstractmethod
47
- def _create_consumer(self) -> "BaseConsumer[Packed]":
44
+ def _create_consumer(self) -> "BaseConsumer[Message]":
48
45
 
49
46
  pass
50
47
 
51
48
  @property
52
- def message(self) -> BaseMessage[Packed]:
49
+ def serializer(self) -> type[BaseSerializer[Message]]:
53
50
 
54
- return self._message
51
+ return self._serializer
55
52
 
56
53
  async def publish(
57
54
  self,
58
55
  coro_args: tuple[t.Any, ...],
59
56
  coro_kwargs: dict[str, t.Any] | None = None,
60
- **kwargs: t.Any) -> None:
57
+ *,
58
+ timeout: float | None = None) -> None:
61
59
 
62
- await self._producer.publish(coro_args, coro_kwargs, **kwargs)
60
+ await self._producer.publish(coro_args, coro_kwargs, timeout=timeout)
63
61
 
64
62
  async def start_consumer(self) -> None:
65
63
 
@@ -3,7 +3,7 @@
3
3
  import asyncio
4
4
  import typing as t
5
5
 
6
- from queue_func.message.base import Packed
6
+ from queue_func.serializer.base import Message
7
7
  from queue_func.broker.base import BaseBroker as _BaseBroker
8
8
  from queue_func.producer.queue import Producer
9
9
  from queue_func.consumer.queue import Consumer
@@ -12,7 +12,7 @@ if t.TYPE_CHECKING:
12
12
  from queue_func.config.queue import Config
13
13
 
14
14
 
15
- class Broker(_BaseBroker["Config", Packed]):
15
+ class Broker(_BaseBroker["Config", Message]):
16
16
  """内存队列通道。队列由这里创建,再交给 Producer 和 Consumer。"""
17
17
 
18
18
  __slots__ = (
@@ -20,23 +20,23 @@ class Broker(_BaseBroker["Config", Packed]):
20
20
  )
21
21
 
22
22
  def __init__(self, config: "Config"):
23
- self._queue: asyncio.Queue[Packed] = asyncio.Queue(maxsize=config.maxsize)
23
+ self._queue: asyncio.Queue[Message] = asyncio.Queue(maxsize=config.maxsize)
24
24
  super().__init__(config)
25
25
 
26
- def _create_producer(self) -> Producer[Packed]:
26
+ def _create_producer(self) -> Producer[Message]:
27
27
 
28
28
  return Producer(
29
29
  queue=self._queue,
30
30
  publish_timeout=self._config.publish_timeout,
31
- message=self._message,
31
+ serializer=self._serializer,
32
32
  )
33
33
 
34
- def _create_consumer(self) -> Consumer[Packed]:
34
+ def _create_consumer(self) -> Consumer[Message]:
35
35
 
36
36
  return Consumer(
37
37
  queue=self._queue,
38
38
  consume_timeout=self._config.consume_timeout,
39
- message=self._message,
39
+ serializer=self._serializer,
40
40
  coro=self._config.coro,
41
41
  enable_consumer=self._config.enable_consumer,
42
42
  pool_executor_cls=self._config.consumer_pool_executor_cls,
@@ -5,10 +5,8 @@ import typing as t
5
5
  from pydantic.dataclasses import dataclass as pyd_dataclass
6
6
 
7
7
  from queue_func.config.utils import ExtraIgnoreConfig
8
- from queue_func.message.base import BaseMessage
9
- from queue_func.message.general import Message
10
8
  from queue_func.serializer.base import BaseSerializer
11
- from queue_func.serializer.orjson_ser import OrJSONSerializer
9
+ from queue_func.serializer.orjson_ser import Serializer
12
10
  from queue_func.pool_executor.base import BasePoolExecutor
13
11
  from queue_func.pool_executor.general import PoolExecutor
14
12
 
@@ -24,9 +22,7 @@ class Config:
24
22
  consumer_pool_maxsize: int = 200
25
23
 
26
24
  # broker
27
- message_cls: type[BaseMessage] = Message
28
- message_serializer_cls: type[BaseSerializer] = OrJSONSerializer
29
- enable_message_serializer: bool = True
25
+ serializer_cls: type[BaseSerializer] = Serializer
30
26
 
31
27
  # producer
32
28
  publish_timeout: float | None = None
@@ -5,6 +5,8 @@ from pydantic.dataclasses import dataclass as pyd_dataclass
5
5
 
6
6
  from queue_func.config.utils import ExtraIgnoreConfig
7
7
  from queue_func.config.general import Config as _Config
8
+ from queue_func.serializer.base import BaseSerializer
9
+ from queue_func.serializer.raw import Serializer
8
10
 
9
11
 
10
12
  @pyd_dataclass(frozen=True, config=ExtraIgnoreConfig)
@@ -12,3 +14,4 @@ class Config(_Config):
12
14
 
13
15
  # broker
14
16
  maxsize: int = 200
17
+ serializer_cls: type[BaseSerializer] = Serializer
@@ -7,14 +7,14 @@ import contextlib
7
7
  import typing as t
8
8
  from functools import wraps
9
9
 
10
- from queue_func.message.base import BaseMessage, Packed
10
+ from queue_func.serializer.base import BaseSerializer, Message
11
11
  from queue_func.pool_executor.base import BasePoolExecutor
12
12
 
13
13
 
14
- class BaseConsumer(t.Generic[Packed], metaclass=abc.ABCMeta):
14
+ class BaseConsumer(t.Generic[Message], metaclass=abc.ABCMeta):
15
15
 
16
16
  __slots__ = (
17
- "_message",
17
+ "_serializer",
18
18
  "_coro",
19
19
  "_enable_consumer",
20
20
  "_pool_executor",
@@ -25,13 +25,13 @@ class BaseConsumer(t.Generic[Packed], metaclass=abc.ABCMeta):
25
25
 
26
26
  def __init__(
27
27
  self,
28
- message: BaseMessage[Packed],
28
+ serializer: type[BaseSerializer[Message]],
29
29
  coro: t.Callable[..., t.Coroutine],
30
30
  enable_consumer: bool,
31
31
  pool_executor_cls: type[BasePoolExecutor],
32
32
  pool_maxsize: int):
33
33
 
34
- self._message = message
34
+ self._serializer = serializer
35
35
  self._coro = coro
36
36
  self._enable_consumer = enable_consumer
37
37
  self._pool_executor = self._init_pool_executor(pool_executor_cls, pool_maxsize)
@@ -3,12 +3,12 @@
3
3
  import asyncio
4
4
  import typing as t
5
5
 
6
- from queue_func.message.base import BaseMessage, Packed
6
+ from queue_func.serializer.base import BaseSerializer, Message
7
7
  from queue_func.pool_executor.base import BasePoolExecutor
8
8
  from queue_func.consumer.base import BaseConsumer as _BaseConsumer
9
9
 
10
10
 
11
- class Consumer(_BaseConsumer[Packed]):
11
+ class Consumer(_BaseConsumer[Message]):
12
12
 
13
13
  __slots__ = (
14
14
  "_queue",
@@ -17,16 +17,16 @@ class Consumer(_BaseConsumer[Packed]):
17
17
 
18
18
  def __init__(
19
19
  self,
20
- queue: asyncio.Queue[Packed],
20
+ queue: asyncio.Queue[Message],
21
21
  consume_timeout: float,
22
- message: BaseMessage[Packed],
22
+ serializer: type[BaseSerializer[Message]],
23
23
  coro: t.Callable[..., t.Coroutine],
24
24
  enable_consumer: bool,
25
25
  pool_executor_cls: type[BasePoolExecutor],
26
26
  pool_maxsize: int):
27
27
 
28
28
  super().__init__(
29
- message,
29
+ serializer,
30
30
  coro,
31
31
  enable_consumer,
32
32
  pool_executor_cls,
@@ -39,13 +39,13 @@ class Consumer(_BaseConsumer[Packed]):
39
39
 
40
40
  while (not self._stop_flag) or (not self._queue.empty()):
41
41
  try:
42
- message: Packed = await asyncio.wait_for(
42
+ packed: Message = await asyncio.wait_for(
43
43
  self._queue.get(),
44
44
  timeout=self._consume_timeout,
45
45
  )
46
46
  except asyncio.TimeoutError:
47
47
  continue
48
- coro_args, coro_kwargs = self._message.unpack(message)
48
+ coro_args, coro_kwargs = self._serializer.unpack(packed)
49
49
  await self._dispatch(coro_args, coro_kwargs)
50
50
  self._queue.task_done()
51
51
 
@@ -0,0 +1,7 @@
1
+ # coding: utf-8
2
+
3
+
4
+ class PublishTimeoutError(TimeoutError):
5
+ """入队在给定时间内未完成"""
6
+
7
+ pass
@@ -9,7 +9,6 @@ from queue_func.factory.registry import build_broker
9
9
  if t.TYPE_CHECKING:
10
10
  from queue_func.broker.base import BaseBroker
11
11
  from queue_func.config.general import Config as GeneralConfig
12
- from queue_func.message.base import BaseMessage
13
12
  from queue_func.pool_executor.base import BasePoolExecutor
14
13
  from queue_func.serializer.base import BaseSerializer
15
14
 
@@ -46,9 +45,10 @@ class QueueFunc(t.Generic[_P, _R]):
46
45
  self,
47
46
  *,
48
47
  args: tuple[t.Any, ...] = (),
49
- kwargs: dict[str, t.Any] | None = None) -> None:
48
+ kwargs: dict[str, t.Any] | None = None,
49
+ timeout: float | None = None) -> None:
50
50
 
51
- await self._broker.publish(coro_args=args, coro_kwargs=kwargs)
51
+ await self._broker.publish(coro_args=args, coro_kwargs=kwargs, timeout=timeout)
52
52
 
53
53
  @property
54
54
  def broker(self) -> "BaseBroker[t.Any, t.Any]":
@@ -76,9 +76,7 @@ def queue(
76
76
  consume_timeout: float = ...,
77
77
  consumer_pool_executor_cls: type["BasePoolExecutor"] = ...,
78
78
  consumer_pool_maxsize: int = ...,
79
- message_cls: type["BaseMessage"] = ...,
80
- message_serializer_cls: type["BaseSerializer"] = ...,
81
- enable_message_serializer: bool = ...,
79
+ serializer_cls: type["BaseSerializer"] = ...,
82
80
  publish_timeout: float | None = ...,
83
81
  maxsize: int = ...,
84
82
  ) -> t.Callable[[t.Callable[_P, t.Coroutine[t.Any, t.Any, _R]]], QueueFunc[_P, _R]]: