onestep 0.1.76__tar.gz → 0.1.78__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.
Potentially problematic release.
This version of onestep might be problematic. Click here for more details.
- {onestep-0.1.76 → onestep-0.1.78}/PKG-INFO +1 -1
- {onestep-0.1.76 → onestep-0.1.78}/pyproject.toml +1 -1
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/__init__.py +4 -4
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/broker/base.py +40 -38
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/broker/rabbitmq.py +18 -13
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/message.py +8 -4
- onestep-0.1.78/src/onestep/store/__init__.py +2 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/store/rabbitmq.py +20 -13
- onestep-0.1.76/src/onestep/store/__init__.py +0 -1
- {onestep-0.1.76 → onestep-0.1.78}/README.md +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/broker/__init__.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/broker/cron.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/broker/memory.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/broker/webhook.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/exception.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/middleware/__init__.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/middleware/base.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/middleware/config.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/onestep.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/retry.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/signal.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/state.py +0 -0
- {onestep-0.1.76 → onestep-0.1.78}/src/onestep/worker.py +0 -0
|
@@ -19,7 +19,7 @@ from .exception import (
|
|
|
19
19
|
|
|
20
20
|
__all__ = [
|
|
21
21
|
'step',
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
# broker
|
|
24
24
|
'BaseBroker',
|
|
25
25
|
'BaseConsumer',
|
|
@@ -29,7 +29,7 @@ __all__ = [
|
|
|
29
29
|
'RabbitMQBroker',
|
|
30
30
|
'WebHookBroker',
|
|
31
31
|
'CronBroker',
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
# retry
|
|
34
34
|
'BaseRetry',
|
|
35
35
|
'NeverRetry',
|
|
@@ -40,7 +40,7 @@ __all__ = [
|
|
|
40
40
|
# error callback
|
|
41
41
|
'BaseErrorCallback',
|
|
42
42
|
'NackErrorCallBack',
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
# middleware
|
|
45
45
|
'BaseMiddleware',
|
|
46
46
|
'BaseConfigMiddleware',
|
|
@@ -48,7 +48,7 @@ __all__ = [
|
|
|
48
48
|
'NacosConsumeConfigMiddleware',
|
|
49
49
|
'RedisPublishConfigMiddleware',
|
|
50
50
|
'RedisConsumeConfigMiddleware',
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
# exception
|
|
53
53
|
'StopMiddleware',
|
|
54
54
|
'DropMessage',
|
|
@@ -2,73 +2,74 @@
|
|
|
2
2
|
import abc
|
|
3
3
|
import json
|
|
4
4
|
from queue import Queue, Empty
|
|
5
|
+
from typing import Any
|
|
5
6
|
|
|
6
7
|
from ..exception import StopMiddleware
|
|
7
8
|
from ..message import Message
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class BaseBroker:
|
|
11
|
-
|
|
12
|
+
|
|
12
13
|
def __init__(self, name=None, queue=None, middlewares=None):
|
|
13
14
|
self.queue = queue
|
|
14
15
|
self.name = name or "broker"
|
|
15
16
|
self.middlewares = []
|
|
16
|
-
|
|
17
|
+
|
|
17
18
|
if middlewares:
|
|
18
19
|
for middleware in middlewares:
|
|
19
20
|
self.add_middleware(middleware)
|
|
20
|
-
|
|
21
|
+
|
|
21
22
|
def add_middleware(self, middleware):
|
|
22
23
|
self.middlewares.append(middleware)
|
|
23
|
-
|
|
24
|
+
|
|
24
25
|
def send(self, message):
|
|
25
26
|
"""对消息进行预处理,然后再发送"""
|
|
26
27
|
if not isinstance(message, Message):
|
|
27
28
|
message = Message(body=message)
|
|
28
29
|
# TODO: 对消息发送进行N次重试,确保消息发送成功。
|
|
29
30
|
return self.publish(message.to_json())
|
|
30
|
-
|
|
31
|
+
|
|
31
32
|
@abc.abstractmethod
|
|
32
|
-
def publish(self, message):
|
|
33
|
+
def publish(self, message: Any):
|
|
33
34
|
"""
|
|
34
35
|
如果当前Broker是Job的to_broker, 则必须实现此方法
|
|
35
36
|
"""
|
|
36
37
|
raise NotImplementedError('Please implement in subclasses.')
|
|
37
|
-
|
|
38
|
+
|
|
38
39
|
@abc.abstractmethod
|
|
39
40
|
def consume(self, *args, **kwargs):
|
|
40
41
|
"""
|
|
41
42
|
如果当前Broker是Job的from_broker, 则必须实现此方法
|
|
42
43
|
"""
|
|
43
44
|
raise NotImplementedError('Please implement in subclasses.')
|
|
44
|
-
|
|
45
|
+
|
|
45
46
|
@abc.abstractmethod
|
|
46
|
-
def confirm(self, message):
|
|
47
|
+
def confirm(self, message: Message):
|
|
47
48
|
"""确认消息"""
|
|
48
49
|
raise NotImplementedError('Please implement in subclasses.')
|
|
49
|
-
|
|
50
|
+
|
|
50
51
|
@abc.abstractmethod
|
|
51
|
-
def reject(self, message):
|
|
52
|
+
def reject(self, message: Message):
|
|
52
53
|
"""拒绝消息"""
|
|
53
54
|
raise NotImplementedError('Please implement in subclasses.')
|
|
54
|
-
|
|
55
|
+
|
|
55
56
|
@abc.abstractmethod
|
|
56
|
-
def requeue(self, message, is_source=False):
|
|
57
|
+
def requeue(self, message: Message, is_source=False):
|
|
57
58
|
"""
|
|
58
59
|
重发消息:先拒绝 再 重入
|
|
59
60
|
is_source = False 重入使用消息的当前状态
|
|
60
61
|
is_source = True 重入使用消息的初始状态
|
|
61
62
|
"""
|
|
62
63
|
raise NotImplementedError('Please implement in subclasses.')
|
|
63
|
-
|
|
64
|
+
|
|
64
65
|
def before_emit(self, signal, *args, **kwargs):
|
|
65
66
|
signal = "before_" + signal
|
|
66
67
|
self._emit(signal, *args, **kwargs)
|
|
67
|
-
|
|
68
|
+
|
|
68
69
|
def after_emit(self, signal, *args, **kwargs):
|
|
69
70
|
signal = "after_" + signal
|
|
70
71
|
self._emit(signal, *args, **kwargs)
|
|
71
|
-
|
|
72
|
+
|
|
72
73
|
def _emit(self, signal, *args, **kwargs):
|
|
73
74
|
for middleware in self.middlewares:
|
|
74
75
|
if not hasattr(middleware, signal):
|
|
@@ -77,74 +78,75 @@ class BaseBroker:
|
|
|
77
78
|
getattr(middleware, signal)(self, *args, **kwargs)
|
|
78
79
|
except StopMiddleware:
|
|
79
80
|
break
|
|
80
|
-
|
|
81
|
+
|
|
81
82
|
def __repr__(self):
|
|
82
83
|
return f"<{self.__class__.__name__} {self.name}>"
|
|
83
|
-
|
|
84
|
+
|
|
84
85
|
def __str__(self):
|
|
85
86
|
return self.name
|
|
86
87
|
|
|
87
88
|
|
|
88
89
|
class BaseConsumer:
|
|
89
|
-
|
|
90
|
+
|
|
90
91
|
def __init__(self, queue: Queue, *args, **kwargs):
|
|
91
92
|
self.queue = queue
|
|
92
93
|
self.timeout = kwargs.pop("timeout", 1000)
|
|
93
|
-
|
|
94
|
+
|
|
94
95
|
@abc.abstractmethod
|
|
95
|
-
def _to_message(self, data):
|
|
96
|
+
def _to_message(self, data: Any):
|
|
96
97
|
"""
|
|
97
98
|
转换消息内容到 Message , 则必须实现此方法
|
|
98
99
|
"""
|
|
99
100
|
raise NotImplementedError('Please implement in subclasses.')
|
|
100
|
-
|
|
101
|
+
|
|
101
102
|
def __next__(self):
|
|
102
103
|
try:
|
|
103
|
-
|
|
104
|
+
data = self.queue.get(timeout=self.timeout / 1000)
|
|
105
|
+
return self._to_message(data)
|
|
104
106
|
except Empty:
|
|
105
107
|
return None
|
|
106
|
-
|
|
108
|
+
|
|
107
109
|
def __iter__(self):
|
|
108
110
|
return self
|
|
109
111
|
|
|
110
112
|
|
|
111
113
|
class BaseLocalBroker(BaseBroker):
|
|
112
|
-
|
|
114
|
+
|
|
113
115
|
def __init__(self, *args, **kwargs):
|
|
114
116
|
super().__init__(*args, **kwargs)
|
|
115
117
|
self.queue = Queue()
|
|
116
|
-
|
|
117
|
-
def publish(self, message):
|
|
118
|
+
|
|
119
|
+
def publish(self, message: Any):
|
|
118
120
|
self.queue.put_nowait(message)
|
|
119
|
-
|
|
121
|
+
|
|
120
122
|
def consume(self, *args, **kwargs):
|
|
121
123
|
return BaseLocalConsumer(self.queue, *args, **kwargs)
|
|
122
|
-
|
|
123
|
-
def confirm(self, message):
|
|
124
|
+
|
|
125
|
+
def confirm(self, message: Message):
|
|
124
126
|
"""确认消息"""
|
|
125
127
|
pass
|
|
126
|
-
|
|
127
|
-
def reject(self, message):
|
|
128
|
+
|
|
129
|
+
def reject(self, message: Message):
|
|
128
130
|
"""拒绝消息"""
|
|
129
131
|
pass
|
|
130
|
-
|
|
131
|
-
def requeue(self, message, is_source=False):
|
|
132
|
+
|
|
133
|
+
def requeue(self, message: Message, is_source=False):
|
|
132
134
|
"""重发消息:先拒绝 再 重入"""
|
|
133
135
|
if is_source:
|
|
134
136
|
self.publish(message.msg)
|
|
135
137
|
else:
|
|
136
138
|
self.send(message)
|
|
137
|
-
|
|
139
|
+
|
|
138
140
|
def __repr__(self):
|
|
139
141
|
return f"<{self.__class__.__name__} {self.name}>"
|
|
140
|
-
|
|
142
|
+
|
|
141
143
|
def __str__(self):
|
|
142
144
|
return self.name
|
|
143
145
|
|
|
144
146
|
|
|
145
147
|
class BaseLocalConsumer(BaseConsumer):
|
|
146
|
-
|
|
147
|
-
def _to_message(self, data):
|
|
148
|
+
|
|
149
|
+
def _to_message(self, data: Any):
|
|
148
150
|
message = Message(msg=data)
|
|
149
151
|
try:
|
|
150
152
|
body = json.loads(data)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import threading
|
|
3
3
|
from queue import Queue
|
|
4
|
-
from typing import Optional, Dict
|
|
4
|
+
from typing import Optional, Dict, Any
|
|
5
5
|
|
|
6
6
|
import amqpstorm
|
|
7
7
|
|
|
8
8
|
from .base import BaseBroker, BaseConsumer
|
|
9
|
-
from ..store.rabbitmq import
|
|
9
|
+
from ..store.rabbitmq import RabbitMQStore
|
|
10
10
|
from ..message import Message
|
|
11
11
|
|
|
12
12
|
|
|
@@ -17,12 +17,12 @@ class RabbitMQBroker(BaseBroker):
|
|
|
17
17
|
self.queue_name = queue_name
|
|
18
18
|
self.queue = Queue()
|
|
19
19
|
params = params or {}
|
|
20
|
-
self.client =
|
|
20
|
+
self.client = RabbitMQStore(**params)
|
|
21
21
|
self.client.declare_queue(self.queue_name)
|
|
22
22
|
self.prefetch = prefetch
|
|
23
23
|
|
|
24
24
|
def _consume(self, *args, **kwargs):
|
|
25
|
-
def callback(message):
|
|
25
|
+
def callback(message: amqpstorm.Message):
|
|
26
26
|
self.queue.put(message)
|
|
27
27
|
|
|
28
28
|
prefetch = kwargs.pop("prefetch", self.prefetch)
|
|
@@ -32,23 +32,28 @@ class RabbitMQBroker(BaseBroker):
|
|
|
32
32
|
threading.Thread(target=self._consume, *args, **kwargs).start()
|
|
33
33
|
return RabbitMQConsumer(self.queue)
|
|
34
34
|
|
|
35
|
-
def publish(self, message):
|
|
35
|
+
def publish(self, message: Any):
|
|
36
36
|
self.client.send(self.queue_name, message)
|
|
37
37
|
|
|
38
|
-
def confirm(self, message):
|
|
38
|
+
def confirm(self, message: Message):
|
|
39
39
|
"""确认消息"""
|
|
40
|
-
message.msg.
|
|
40
|
+
self.client.channel.basic.ack(message.msg.delivery_tag)
|
|
41
41
|
|
|
42
|
-
def reject(self, message):
|
|
42
|
+
def reject(self, message: Message):
|
|
43
43
|
"""拒绝消息"""
|
|
44
|
-
message.msg.
|
|
44
|
+
self.client.channel.basic.nack(message.msg.delivery_tag, requeue=False)
|
|
45
45
|
|
|
46
|
-
def requeue(self, message, is_source=False):
|
|
47
|
-
"""
|
|
46
|
+
def requeue(self, message: Message, is_source=False):
|
|
47
|
+
"""
|
|
48
|
+
重发消息:先拒绝 再 重入
|
|
49
|
+
|
|
50
|
+
:param message: 消息
|
|
51
|
+
:param is_source: 是否是源消息,True: 使用消息的最新数据重入当前队列,False: 使用消息的最新数据重入当前队列
|
|
52
|
+
"""
|
|
48
53
|
if is_source:
|
|
49
|
-
message.msg.
|
|
54
|
+
self.client.channel.basic.nack(message.msg.delivery_tag, requeue=True)
|
|
50
55
|
else:
|
|
51
|
-
message.msg.
|
|
56
|
+
self.client.channel.basic.nack(message.msg.delivery_tag, requeue=False)
|
|
52
57
|
self.send(message)
|
|
53
58
|
|
|
54
59
|
|
|
@@ -115,14 +115,18 @@ class Message:
|
|
|
115
115
|
self.broker.confirm(self)
|
|
116
116
|
|
|
117
117
|
def reject(self):
|
|
118
|
-
"""拒绝消息
|
|
118
|
+
"""拒绝消息"""
|
|
119
119
|
if self.broker:
|
|
120
120
|
self.broker.reject(self)
|
|
121
121
|
|
|
122
|
-
def requeue(self):
|
|
123
|
-
"""
|
|
122
|
+
def requeue(self, is_source=False):
|
|
123
|
+
"""
|
|
124
|
+
重发消息:先拒绝 再 重入
|
|
125
|
+
|
|
126
|
+
:param is_source: 是否是源消息,True: 使用消息的最新数据重入当前队列,False: 使用消息的最新数据重入当前队列
|
|
127
|
+
"""
|
|
124
128
|
if self.broker:
|
|
125
|
-
self.broker.requeue(self)
|
|
129
|
+
self.broker.requeue(self, is_source=is_source)
|
|
126
130
|
|
|
127
131
|
def __getattr__(self, item):
|
|
128
132
|
return None
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import time
|
|
2
3
|
from threading import local
|
|
3
4
|
import amqpstorm
|
|
4
5
|
from amqpstorm.exception import AMQPConnectionError
|
|
@@ -9,8 +10,8 @@ MAX_CONNECTION_ATTEMPTS = float('inf') # 最大连接重试次数
|
|
|
9
10
|
logger = logging.Logger(__name__)
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
class
|
|
13
|
-
|
|
13
|
+
class RabbitMQStore:
|
|
14
|
+
|
|
14
15
|
def __init__(self, *, confirm_delivery=True, host=None, port=None, username=None, password=None,
|
|
15
16
|
**kwargs):
|
|
16
17
|
"""
|
|
@@ -31,33 +32,34 @@ class RabbitmqStore:
|
|
|
31
32
|
if kwargs:
|
|
32
33
|
self.parameters.update(kwargs)
|
|
33
34
|
self.confirm_delivery = confirm_delivery
|
|
34
|
-
|
|
35
|
+
|
|
35
36
|
def _create_connection(self):
|
|
36
37
|
attempts = 1
|
|
37
38
|
while attempts <= MAX_CONNECTION_ATTEMPTS:
|
|
38
39
|
try:
|
|
40
|
+
# logger.warning("RabbitmqStore connection try: attempts=%s", attempts)
|
|
39
41
|
return amqpstorm.Connection(**self.parameters)
|
|
40
42
|
except AMQPConnectionError as exc:
|
|
41
43
|
attempts += 1
|
|
42
44
|
logger.warning("RabbitmqStore connection error: %s", exc)
|
|
43
45
|
raise AMQPConnectionError("RabbitmqStore connection error, max attempts reached")
|
|
44
|
-
|
|
46
|
+
|
|
45
47
|
@property
|
|
46
|
-
def connection(self):
|
|
48
|
+
def connection(self) -> amqpstorm.Connection:
|
|
47
49
|
connection = getattr(self.state, "connection", None)
|
|
48
50
|
if connection is None or not connection.is_open:
|
|
49
51
|
connection = self.state.connection = self._create_connection()
|
|
50
52
|
return connection
|
|
51
|
-
|
|
53
|
+
|
|
52
54
|
@connection.deleter
|
|
53
55
|
def connection(self):
|
|
54
56
|
if _connection := getattr(self.state, "connection", None):
|
|
55
57
|
_connection.close()
|
|
56
58
|
del self.state.connection
|
|
57
59
|
del self.state.channel
|
|
58
|
-
|
|
60
|
+
|
|
59
61
|
@property
|
|
60
|
-
def channel(self):
|
|
62
|
+
def channel(self) -> amqpstorm.Channel:
|
|
61
63
|
connection = getattr(self.state, "connection", None)
|
|
62
64
|
channel = getattr(self.state, "channel", None)
|
|
63
65
|
if all([connection, channel]) and all([connection.is_open, channel.is_open]):
|
|
@@ -66,13 +68,13 @@ class RabbitmqStore:
|
|
|
66
68
|
if self.confirm_delivery:
|
|
67
69
|
channel.confirm_deliveries()
|
|
68
70
|
return channel
|
|
69
|
-
|
|
71
|
+
|
|
70
72
|
def declare_queue(self, queue_name, arguments=None):
|
|
71
73
|
"""声明队列"""
|
|
72
74
|
if arguments is None:
|
|
73
75
|
arguments = {}
|
|
74
76
|
return self.channel.queue.declare(queue_name, durable=True, arguments=arguments)
|
|
75
|
-
|
|
77
|
+
|
|
76
78
|
def send(self, queue_name, message, priority=None, **kwargs):
|
|
77
79
|
"""发送消息"""
|
|
78
80
|
attempts = 1
|
|
@@ -88,16 +90,16 @@ class RabbitmqStore:
|
|
|
88
90
|
attempts += 1
|
|
89
91
|
if attempts > MAX_SEND_ATTEMPTS:
|
|
90
92
|
raise exc
|
|
91
|
-
|
|
93
|
+
|
|
92
94
|
def flush_queue(self, queue_name):
|
|
93
95
|
"""清空队列"""
|
|
94
96
|
self.channel.queue.purge(queue_name)
|
|
95
|
-
|
|
97
|
+
|
|
96
98
|
def get_message_counts(self, queue_name: str) -> int:
|
|
97
99
|
"""获取消息数量"""
|
|
98
100
|
queue_response = self.declare_queue(queue_name)
|
|
99
101
|
return queue_response.get("message_count", 0)
|
|
100
|
-
|
|
102
|
+
|
|
101
103
|
def start_consuming(self, queue_name, callback, prefetch=1, **kwargs):
|
|
102
104
|
"""开始消费"""
|
|
103
105
|
while True:
|
|
@@ -108,6 +110,11 @@ class RabbitmqStore:
|
|
|
108
110
|
except AMQPConnectionError:
|
|
109
111
|
logger.warning("RabbitmqStore consume connection error, reconnecting...")
|
|
110
112
|
del self.connection
|
|
113
|
+
time.sleep(1)
|
|
111
114
|
except Exception as e:
|
|
112
115
|
logger.exception(f"RabbitmqStore consume error<{e}>, reconnecting...")
|
|
113
116
|
del self.connection
|
|
117
|
+
time.sleep(1)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
RabbitmqStore = RabbitMQStore # 兼容旧版本
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .rabbitmq import RabbitmqStore
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|