FlowerPower 0.20.0__py3-none-any.whl → 0.30.0__py3-none-any.whl
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.
- flowerpower/__init__.py +2 -6
- flowerpower/cfg/__init__.py +4 -11
- flowerpower/cfg/base.py +29 -25
- flowerpower/cfg/pipeline/__init__.py +3 -3
- flowerpower/cfg/pipeline/_schedule.py +32 -0
- flowerpower/cfg/pipeline/adapter.py +0 -5
- flowerpower/cfg/pipeline/builder.py +377 -0
- flowerpower/cfg/pipeline/run.py +89 -0
- flowerpower/cfg/project/__init__.py +8 -21
- flowerpower/cfg/project/adapter.py +0 -12
- flowerpower/cli/__init__.py +2 -28
- flowerpower/cli/pipeline.py +10 -4
- flowerpower/flowerpower.py +275 -585
- flowerpower/pipeline/base.py +19 -10
- flowerpower/pipeline/io.py +52 -46
- flowerpower/pipeline/manager.py +149 -91
- flowerpower/pipeline/pipeline.py +159 -87
- flowerpower/pipeline/registry.py +68 -33
- flowerpower/pipeline/visualizer.py +4 -4
- flowerpower/plugins/{_io → io}/__init__.py +1 -1
- flowerpower/settings/__init__.py +0 -2
- flowerpower/settings/{backend.py → _backend.py} +0 -19
- flowerpower/settings/logging.py +1 -1
- flowerpower/utils/logging.py +24 -12
- flowerpower/utils/misc.py +17 -0
- flowerpower-0.30.0.dist-info/METADATA +451 -0
- flowerpower-0.30.0.dist-info/RECORD +42 -0
- flowerpower/cfg/pipeline/schedule.py +0 -74
- flowerpower/cfg/project/job_queue.py +0 -111
- flowerpower/cli/job_queue.py +0 -1329
- flowerpower/cli/mqtt.py +0 -174
- flowerpower/job_queue/__init__.py +0 -205
- flowerpower/job_queue/base.py +0 -611
- flowerpower/job_queue/rq/__init__.py +0 -10
- flowerpower/job_queue/rq/_trigger.py +0 -37
- flowerpower/job_queue/rq/concurrent_workers/gevent_worker.py +0 -226
- flowerpower/job_queue/rq/concurrent_workers/thread_worker.py +0 -228
- flowerpower/job_queue/rq/manager.py +0 -1893
- flowerpower/job_queue/rq/setup.py +0 -154
- flowerpower/job_queue/rq/utils.py +0 -69
- flowerpower/mqtt.py +0 -12
- flowerpower/plugins/mqtt/__init__.py +0 -12
- flowerpower/plugins/mqtt/cfg.py +0 -17
- flowerpower/plugins/mqtt/manager.py +0 -962
- flowerpower/settings/job_queue.py +0 -31
- flowerpower-0.20.0.dist-info/METADATA +0 -693
- flowerpower-0.20.0.dist-info/RECORD +0 -58
- {flowerpower-0.20.0.dist-info → flowerpower-0.30.0.dist-info}/WHEEL +0 -0
- {flowerpower-0.20.0.dist-info → flowerpower-0.30.0.dist-info}/entry_points.txt +0 -0
- {flowerpower-0.20.0.dist-info → flowerpower-0.30.0.dist-info}/licenses/LICENSE +0 -0
- {flowerpower-0.20.0.dist-info → flowerpower-0.30.0.dist-info}/top_level.txt +0 -0
@@ -1,962 +0,0 @@
|
|
1
|
-
import datetime as dt
|
2
|
-
import random
|
3
|
-
import socket
|
4
|
-
import time
|
5
|
-
from pathlib import Path
|
6
|
-
from types import TracebackType
|
7
|
-
from typing import Any, Callable
|
8
|
-
|
9
|
-
import mmh3
|
10
|
-
from fsspec_utils import AbstractFileSystem, BaseStorageOptions, filesystem
|
11
|
-
from loguru import logger
|
12
|
-
from munch import Munch
|
13
|
-
from paho.mqtt.client import (MQTT_ERR_SUCCESS, CallbackAPIVersion, Client,
|
14
|
-
MQTTMessageInfo)
|
15
|
-
from paho.mqtt.reasoncodes import ReasonCode
|
16
|
-
|
17
|
-
from ...cfg import ProjectConfig
|
18
|
-
from ...cfg.pipeline.run import ExecutorConfig, WithAdapterConfig
|
19
|
-
from ...cfg.project.adapter import AdapterConfig
|
20
|
-
from ...pipeline.manager import PipelineManager
|
21
|
-
from ...utils.logging import setup_logging
|
22
|
-
from .cfg import MqttConfig
|
23
|
-
|
24
|
-
setup_logging()
|
25
|
-
|
26
|
-
|
27
|
-
class MqttManager:
|
28
|
-
def __init__(
|
29
|
-
self,
|
30
|
-
username: str | None = None,
|
31
|
-
password: str | None = None,
|
32
|
-
host: str | None = "localhost",
|
33
|
-
port: int | None = 1883,
|
34
|
-
topic: str | None = None,
|
35
|
-
first_reconnect_delay: int = 1,
|
36
|
-
max_reconnect_count: int = 5,
|
37
|
-
reconnect_rate: int = 2,
|
38
|
-
max_reconnect_delay: int = 60,
|
39
|
-
transport: str = "tcp",
|
40
|
-
clean_session: bool = True,
|
41
|
-
client_id: str | None = None,
|
42
|
-
client_id_suffix: str | None = None,
|
43
|
-
**kwargs,
|
44
|
-
):
|
45
|
-
if "user" in kwargs:
|
46
|
-
username = kwargs["user"]
|
47
|
-
if "pw" in kwargs:
|
48
|
-
password = kwargs["pw"]
|
49
|
-
|
50
|
-
self.topic = topic
|
51
|
-
|
52
|
-
self._username = username
|
53
|
-
self._password = password
|
54
|
-
self._host = host
|
55
|
-
self._port = port
|
56
|
-
self._first_reconnect_delay = first_reconnect_delay
|
57
|
-
self._max_reconnect_count = max_reconnect_count
|
58
|
-
self._reconnect_rate = reconnect_rate
|
59
|
-
self._max_reconnect_delay = max_reconnect_delay
|
60
|
-
self._transport = transport
|
61
|
-
|
62
|
-
self._clean_session = clean_session
|
63
|
-
self._client_id = client_id
|
64
|
-
self._client_id_suffix = client_id_suffix
|
65
|
-
|
66
|
-
self._client = None
|
67
|
-
|
68
|
-
@classmethod
|
69
|
-
def from_event_broker(cls, base_dir: str | None = None):
|
70
|
-
"""Create a MqttManager instance from the event broker configuration.
|
71
|
-
|
72
|
-
Args:
|
73
|
-
base_dir (str | None): Base directory for the project. If None, uses the current working directory.
|
74
|
-
|
75
|
-
Returns:
|
76
|
-
MqttManager: An instance of MqttManager configured with the event broker settings.
|
77
|
-
"""
|
78
|
-
base_dir = base_dir or str(Path.cwd())
|
79
|
-
|
80
|
-
jq_backend = ProjectConfig.load(base_dir=base_dir).job_queue.backend
|
81
|
-
if jq_backend is None:
|
82
|
-
raise ValueError(
|
83
|
-
"No MQTT event broker configuration found. Recheck the provided `base_dir`.\n"
|
84
|
-
"If you are not using a MQTT event broker, initialize the MQTT client using the MQTTManager class.\n"
|
85
|
-
"or use the provide a configuration dict to the MQTTManager.from_dict() method."
|
86
|
-
)
|
87
|
-
if hasattr(jq_backend, "event_broker") is False:
|
88
|
-
raise ValueError(
|
89
|
-
"No MQTT event broker configuration found. Recheck the provided `base_dir`.\n"
|
90
|
-
"If you are not using a MQTT event broker, initialize the MQTT client using the MQTTManager class.\n"
|
91
|
-
"or use the provide a configuration dict to the MQTTManager.from_dict() method."
|
92
|
-
)
|
93
|
-
if jq_backend.event_broker.type != "mqtt":
|
94
|
-
raise ValueError(
|
95
|
-
"No MQTT event broker configuration found. Recheck the provided `base_dir`.\n"
|
96
|
-
"If you are not using a MQTT event broker, initialize the MQTT client using the MQTTManager class.\n"
|
97
|
-
"or use the provide a configuration dict to the MQTTManager.from_dict() method."
|
98
|
-
)
|
99
|
-
else:
|
100
|
-
event_broker_cfg = jq_backend.event_broker
|
101
|
-
return cls(
|
102
|
-
**event_broker_cfg.dict(),
|
103
|
-
)
|
104
|
-
|
105
|
-
@classmethod
|
106
|
-
def from_config(
|
107
|
-
cls,
|
108
|
-
cfg: MqttConfig | None = None,
|
109
|
-
path: str | None = None,
|
110
|
-
fs: AbstractFileSystem | None = None,
|
111
|
-
storage_options: dict | BaseStorageOptions = {},
|
112
|
-
):
|
113
|
-
"""Create a MqttManager instance from the provided configuration.
|
114
|
-
|
115
|
-
Args:
|
116
|
-
cfg (MqttConfig | None): Configuration for the MQTT client. If None, loads from the provided path.
|
117
|
-
path (str | None): Path to the configuration file. If None, uses the default configuration.
|
118
|
-
fs (AbstractFileSystem | None): File system to use for loading the configuration.
|
119
|
-
storage_options (dict | BaseStorageOptions): Storage options for the file system.
|
120
|
-
|
121
|
-
Returns:
|
122
|
-
MqttManager: An instance of MqttManager configured with the provided settings.
|
123
|
-
"""
|
124
|
-
if cfg is None:
|
125
|
-
if path is None:
|
126
|
-
raise ValueError(
|
127
|
-
"No configuration provided. Please provide `config` or `path` to the configuration file."
|
128
|
-
)
|
129
|
-
|
130
|
-
if cfg is None:
|
131
|
-
import os
|
132
|
-
|
133
|
-
if fs is None:
|
134
|
-
fs = filesystem(
|
135
|
-
protocol_or_path=os.path.dirname(path),
|
136
|
-
storage_options=storage_options,
|
137
|
-
)
|
138
|
-
|
139
|
-
cfg = MqttConfig.from_yaml(path=os.path.basename(path), fs=fs)
|
140
|
-
|
141
|
-
return cls(
|
142
|
-
**cfg.dict(),
|
143
|
-
)
|
144
|
-
|
145
|
-
@classmethod
|
146
|
-
def from_dict(cls, cfg: dict):
|
147
|
-
"""Create a MqttManager instance from the provided dictionary configuration.
|
148
|
-
|
149
|
-
Args:
|
150
|
-
cfg (dict): Dictionary containing the configuration for the MQTT client.
|
151
|
-
|
152
|
-
Returns:
|
153
|
-
MqttManager: An instance of MqttManager configured with the provided settings.
|
154
|
-
"""
|
155
|
-
return cls(
|
156
|
-
**cfg,
|
157
|
-
)
|
158
|
-
|
159
|
-
def __enter__(self) -> "MqttManager":
|
160
|
-
self.connect()
|
161
|
-
return self
|
162
|
-
|
163
|
-
def __exit__(
|
164
|
-
self,
|
165
|
-
exc_type: type[BaseException] | None,
|
166
|
-
exc_val: BaseException | None,
|
167
|
-
exc_tb: TracebackType | None,
|
168
|
-
) -> None:
|
169
|
-
# Add any cleanup code here if needed
|
170
|
-
self.disconnect()
|
171
|
-
|
172
|
-
@staticmethod
|
173
|
-
def _on_connect(client, userdata, flags, rc, properties):
|
174
|
-
if rc == 0:
|
175
|
-
logger.info(f"Connected to MQTT Broker {userdata.host}!")
|
176
|
-
logger.info(
|
177
|
-
f"Connected as {userdata.client_id} with clean session {userdata.clean_session}"
|
178
|
-
)
|
179
|
-
else:
|
180
|
-
logger.error(f"Failed to connect, return code {rc}")
|
181
|
-
|
182
|
-
@staticmethod
|
183
|
-
def _on_disconnect(client, userdata, disconnect_flags, rc, properties=None):
|
184
|
-
reconnect_count, reconnect_delay = 0, userdata.first_reconnect_delay
|
185
|
-
|
186
|
-
if userdata.max_reconnect_count == 0:
|
187
|
-
logger.info("Disconnected successfully!")
|
188
|
-
return
|
189
|
-
|
190
|
-
while reconnect_count < userdata.max_reconnect_count:
|
191
|
-
logger.info(f"Reconnecting in {reconnect_delay} seconds...")
|
192
|
-
time.sleep(reconnect_delay)
|
193
|
-
|
194
|
-
try:
|
195
|
-
client.reconnect()
|
196
|
-
logger.info("Reconnected successfully!")
|
197
|
-
return
|
198
|
-
except Exception as err:
|
199
|
-
logger.error(f"{err}. Reconnect failed. Retrying...")
|
200
|
-
|
201
|
-
reconnect_delay *= userdata.reconnect_rate
|
202
|
-
reconnect_delay = min(reconnect_delay, userdata.max_reconnect_delay)
|
203
|
-
reconnect_count += 1
|
204
|
-
logger.info(f"Reconnect failed after {reconnect_count} attempts. Exiting...")
|
205
|
-
|
206
|
-
# @staticmethod
|
207
|
-
# def _on_publish(client, userdata, mid, rc, properties):
|
208
|
-
# logger.info(f"Published message id: {mid} with return code: {rc}")
|
209
|
-
# if rc == 0:
|
210
|
-
# logger.debug("Message published successfully!")
|
211
|
-
# else:
|
212
|
-
# logger.debug(f"Failed to publish message with return code: {rc}")
|
213
|
-
|
214
|
-
@staticmethod
|
215
|
-
def _on_publish(client, userdata, mid, reason_code_obj, properties):
|
216
|
-
"""Callback function for when a message is published."""
|
217
|
-
if isinstance(reason_code_obj, ReasonCode):
|
218
|
-
if not reason_code_obj.is_failure:
|
219
|
-
logger.info(
|
220
|
-
f"Broker acknowledged message_id: {mid} (ReasonCode: {reason_code_obj})"
|
221
|
-
)
|
222
|
-
else:
|
223
|
-
if reason_code_obj.value == 16: # MQTTReasonCode.NoMatchingSubscribers
|
224
|
-
logger.warning(
|
225
|
-
f"Message_id: {mid} published, but broker reported no matching subscribers (ReasonCode: {reason_code_obj})."
|
226
|
-
)
|
227
|
-
else:
|
228
|
-
logger.error(
|
229
|
-
f"Broker acknowledgment error for message_id: {mid}. ReasonCode: {reason_code_obj}"
|
230
|
-
)
|
231
|
-
elif isinstance(reason_code_obj, int): # Fallback for simpler acks (legacy RCs)
|
232
|
-
if reason_code_obj == 0: # MQTT_ERR_SUCCESS
|
233
|
-
logger.info(
|
234
|
-
f"Broker acknowledged message_id: {mid} (Legacy RC: {reason_code_obj})"
|
235
|
-
)
|
236
|
-
else:
|
237
|
-
logger.error(
|
238
|
-
f"Broker acknowledgment error for message_id: {mid}. Legacy RC: {reason_code_obj} ({client.error_string(reason_code_obj)})"
|
239
|
-
)
|
240
|
-
else:
|
241
|
-
logger.warning(
|
242
|
-
f"Message_id: {mid} published. Received unusual RC type in on_publish: {reason_code_obj} (Type: {type(reason_code_obj)})"
|
243
|
-
)
|
244
|
-
|
245
|
-
@staticmethod
|
246
|
-
def _on_subscribe(client, userdata, mid, qos, properties):
|
247
|
-
if isinstance(qos, list):
|
248
|
-
qos_msg = str(qos[0])
|
249
|
-
else:
|
250
|
-
qos_msg = f"and granted QoS {qos[0]}"
|
251
|
-
logger.info(f"Subscribed {qos_msg}")
|
252
|
-
|
253
|
-
def connect(self) -> Client:
|
254
|
-
"""Connect to the MQTT broker.
|
255
|
-
Returns:
|
256
|
-
Client: The connected MQTT client.
|
257
|
-
"""
|
258
|
-
if self._client_id is None and self._clean_session:
|
259
|
-
# Random Client ID when clean session is True
|
260
|
-
self._client_id = f"flowerpower-client-{random.randint(0, 10000)}"
|
261
|
-
elif self._client_id is None and not self._clean_session:
|
262
|
-
# Deterministic Client ID when clean session is False
|
263
|
-
self._client_id = f"flowerpower-client-{
|
264
|
-
mmh3.hash_bytes(
|
265
|
-
str(self._host)
|
266
|
-
+ str(self._port)
|
267
|
-
+ str(self.topic)
|
268
|
-
+ str(socket.gethostname())
|
269
|
-
).hex()
|
270
|
-
}"
|
271
|
-
|
272
|
-
if self._client_id_suffix:
|
273
|
-
self._client_id = f"{self._client_id}-{self._client_id_suffix}"
|
274
|
-
|
275
|
-
logger.debug(
|
276
|
-
f"Client ID: {self._client_id} - Clean session: {self._clean_session}"
|
277
|
-
)
|
278
|
-
client = Client(
|
279
|
-
CallbackAPIVersion.VERSION2,
|
280
|
-
client_id=self._client_id,
|
281
|
-
transport=self._transport,
|
282
|
-
clean_session=self._clean_session,
|
283
|
-
userdata=Munch(
|
284
|
-
user=self._username,
|
285
|
-
pw=self._password,
|
286
|
-
host=self._host,
|
287
|
-
port=self._port,
|
288
|
-
topic=self.topic,
|
289
|
-
first_reconnect_delay=self._first_reconnect_delay,
|
290
|
-
max_reconnect_count=self._max_reconnect_count,
|
291
|
-
reconnect_rate=self._reconnect_rate,
|
292
|
-
max_reconnect_delay=self._max_reconnect_delay,
|
293
|
-
transport=self._transport,
|
294
|
-
client_id=self._client_id,
|
295
|
-
clean_session=self._clean_session,
|
296
|
-
),
|
297
|
-
)
|
298
|
-
if self._password != "" and self._username != "":
|
299
|
-
client.username_pw_set(self._username, self._password)
|
300
|
-
|
301
|
-
client.on_connect = self._on_connect # self._on_connect
|
302
|
-
client.on_disconnect = self._on_disconnect # self._on_disconnect
|
303
|
-
client.on_publish = self._on_publish
|
304
|
-
client.on_subscribe = self._on_subscribe
|
305
|
-
|
306
|
-
client.connect(self._host, self._port)
|
307
|
-
self._client = client
|
308
|
-
# topic = topic or topic
|
309
|
-
if self.topic:
|
310
|
-
self.subscribe()
|
311
|
-
|
312
|
-
def disconnect(self):
|
313
|
-
"""Disconnect from the MQTT broker."""
|
314
|
-
if self._client is None:
|
315
|
-
logger.warning("Client is not connected. Cannot disconnect.")
|
316
|
-
return
|
317
|
-
self._max_reconnect_count = 0
|
318
|
-
self._client._userdata.max_reconnect_count = 0
|
319
|
-
self._client.disconnect()
|
320
|
-
|
321
|
-
def reconnect(self):
|
322
|
-
"""Reconnect to the MQTT broker."""
|
323
|
-
if self._client is None:
|
324
|
-
logger.warning("Client is not connected. Connecting instead.")
|
325
|
-
self.connect()
|
326
|
-
else:
|
327
|
-
self._client.reconnect()
|
328
|
-
|
329
|
-
def publish(
|
330
|
-
self, topic: str, payload: Any, qos: int = 0, retain: bool = False
|
331
|
-
) -> "MQTTMessageInfo | None":
|
332
|
-
"""
|
333
|
-
Publish a message to the MQTT broker.
|
334
|
-
|
335
|
-
Args:
|
336
|
-
topic (str): The topic to publish the message to.
|
337
|
-
payload (Any): The message payload.
|
338
|
-
qos (int, optional): The Quality of Service level. Defaults to 0.
|
339
|
-
retain (bool, optional): Whether to retain the message. Defaults to False.
|
340
|
-
|
341
|
-
Returns:
|
342
|
-
MQTTMessageInfo | None: Information about the published message, or None if an error occurred.
|
343
|
-
"""
|
344
|
-
if self._client is None or not self._client.is_connected():
|
345
|
-
logger.warning(
|
346
|
-
"Client is not connected. Attempting to connect before publishing."
|
347
|
-
)
|
348
|
-
try:
|
349
|
-
self.connect()
|
350
|
-
except Exception as e:
|
351
|
-
logger.error(f"Failed to connect to MQTT broker before publishing: {e}")
|
352
|
-
return None
|
353
|
-
|
354
|
-
try:
|
355
|
-
msg_info = self._client.publish(
|
356
|
-
topic=topic, payload=payload, qos=qos, retain=retain
|
357
|
-
)
|
358
|
-
if msg_info.rc == MQTT_ERR_SUCCESS: # 0:
|
359
|
-
logger.debug(
|
360
|
-
f"Message published successfully. MID: {msg_info.mid}, Topic: {topic}, QoS: {qos}, Retain: {retain}, RC: {msg_info.rc}"
|
361
|
-
)
|
362
|
-
else:
|
363
|
-
logger.error(
|
364
|
-
f"Failed to publish message. Topic: {topic}, QoS: {qos}, Retain: {retain}, RC: {msg_info.rc}, Error: {self._client.error_string(msg_info.rc)}"
|
365
|
-
)
|
366
|
-
return msg_info
|
367
|
-
except Exception as e:
|
368
|
-
logger.error(
|
369
|
-
f"An error occurred while publishing message to topic {topic}: {e}"
|
370
|
-
)
|
371
|
-
return None
|
372
|
-
|
373
|
-
def subscribe(self, topic: str | None = None, qos: int = 2):
|
374
|
-
"""
|
375
|
-
Subscribe to a topic on the MQTT broker.
|
376
|
-
|
377
|
-
Args:
|
378
|
-
topic (str | None): The topic to subscribe to. If None, uses the instance's topic.
|
379
|
-
qos (int): The Quality of Service level.
|
380
|
-
"""
|
381
|
-
if self._client is None or not self._client.is_connected():
|
382
|
-
self.connect()
|
383
|
-
if topic is not None:
|
384
|
-
self.topic = topic
|
385
|
-
self._client.subscribe(self.topic, qos=qos)
|
386
|
-
|
387
|
-
def unsubscribe(self, topic: str | None = None):
|
388
|
-
"""
|
389
|
-
Unsubscribe from a topic on the MQTT broker.
|
390
|
-
|
391
|
-
Args:
|
392
|
-
topic (str | None): The topic to unsubscribe from. If None, uses the instance's topic.
|
393
|
-
"""
|
394
|
-
if self._client is None or not self._client.is_connected():
|
395
|
-
self.connect()
|
396
|
-
if topic is not None:
|
397
|
-
self.topic = topic
|
398
|
-
self._client.unsubscribe(self.topic)
|
399
|
-
|
400
|
-
def register_on_message(self, on_message: Callable):
|
401
|
-
"""
|
402
|
-
Register a callback function to be called when a message is received.
|
403
|
-
|
404
|
-
Args:
|
405
|
-
on_message (Callable): The callback function to register.
|
406
|
-
"""
|
407
|
-
if self._client is None or not self._client.is_connected():
|
408
|
-
self.connect()
|
409
|
-
self._client.on_message = on_message
|
410
|
-
|
411
|
-
def run_in_background(
|
412
|
-
self,
|
413
|
-
on_message: Callable,
|
414
|
-
topic: str | None = None,
|
415
|
-
qos: int = 2,
|
416
|
-
) -> None:
|
417
|
-
"""
|
418
|
-
Run the MQTT client in the background.
|
419
|
-
|
420
|
-
Args:
|
421
|
-
on_message: Callback function to run when a message is received
|
422
|
-
topic: MQTT topic to listen to
|
423
|
-
|
424
|
-
Returns:
|
425
|
-
None
|
426
|
-
|
427
|
-
|
428
|
-
"""
|
429
|
-
if self._client is None or not self._client.is_connected():
|
430
|
-
self.connect()
|
431
|
-
|
432
|
-
if topic:
|
433
|
-
self.subscribe(topic, qos=qos)
|
434
|
-
|
435
|
-
self._client.on_message = on_message
|
436
|
-
self._client.loop_start()
|
437
|
-
|
438
|
-
def run_until_break(
|
439
|
-
self,
|
440
|
-
on_message: Callable,
|
441
|
-
topic: str | None = None,
|
442
|
-
qos: int = 2,
|
443
|
-
):
|
444
|
-
"""
|
445
|
-
Run the MQTT client until a break signal is received.
|
446
|
-
|
447
|
-
Args:
|
448
|
-
on_message: Callback function to run when a message is received
|
449
|
-
topic: MQTT topic to listen to
|
450
|
-
|
451
|
-
Returns:
|
452
|
-
None
|
453
|
-
"""
|
454
|
-
if self._client is None or not self._client.is_connected():
|
455
|
-
self.connect()
|
456
|
-
|
457
|
-
if topic:
|
458
|
-
self.subscribe(topic, qos=qos)
|
459
|
-
|
460
|
-
self._client.on_message = on_message
|
461
|
-
self._client.loop_forever()
|
462
|
-
|
463
|
-
def start_listener(
|
464
|
-
self,
|
465
|
-
on_message: Callable,
|
466
|
-
topic: str | None = None,
|
467
|
-
background: bool = False,
|
468
|
-
qos: int = 2,
|
469
|
-
) -> None:
|
470
|
-
"""
|
471
|
-
Start the MQTT listener.
|
472
|
-
|
473
|
-
Args:
|
474
|
-
on_message: Callback function to run when a message is received
|
475
|
-
topic: MQTT topic to listen to
|
476
|
-
background: Run the listener in the background
|
477
|
-
|
478
|
-
Returns:
|
479
|
-
None
|
480
|
-
"""
|
481
|
-
if background:
|
482
|
-
self.run_in_background(on_message, topic, qos)
|
483
|
-
else:
|
484
|
-
self.run_until_break(on_message, topic, qos)
|
485
|
-
|
486
|
-
def stop_listener(
|
487
|
-
self,
|
488
|
-
) -> None:
|
489
|
-
"""
|
490
|
-
Stop the MQTT listener.
|
491
|
-
|
492
|
-
Returns:
|
493
|
-
None
|
494
|
-
"""
|
495
|
-
self._client.loop_stop()
|
496
|
-
logger.info("Client stopped.")
|
497
|
-
|
498
|
-
# def _run_pipeline(self, **kwargs):
|
499
|
-
# """
|
500
|
-
# Internal method to run a pipeline on a message.
|
501
|
-
# This method is called by the `run_pipeline_on_message` method.
|
502
|
-
# """
|
503
|
-
# # This method is intentionally left empty. It is meant to be overridden
|
504
|
-
# # by the `run_pipeline_on_message` method.
|
505
|
-
# pm.run(self, **kwargs)
|
506
|
-
|
507
|
-
def run_pipeline_on_message(
|
508
|
-
self,
|
509
|
-
name: str,
|
510
|
-
topic: str | None = None,
|
511
|
-
inputs: dict | None = None,
|
512
|
-
final_vars: list | None = None,
|
513
|
-
config: dict | None = None,
|
514
|
-
cache: bool | dict = False,
|
515
|
-
executor_cfg: str | dict | ExecutorConfig | None = None,
|
516
|
-
with_adapter_cfg: dict | WithAdapterConfig | None = None,
|
517
|
-
pipeline_adapter_cfg: dict | AdapterConfig | None = None,
|
518
|
-
project_adapter_cfg: dict | AdapterConfig | None = None,
|
519
|
-
adapter: dict[str, Any] | None = None,
|
520
|
-
reload: bool = False,
|
521
|
-
log_level: str | None = None,
|
522
|
-
result_ttl: float | dt.timedelta = 0,
|
523
|
-
run_in: int | str | dt.timedelta | None = None,
|
524
|
-
max_retries: int | None = None,
|
525
|
-
retry_delay: float | None = None,
|
526
|
-
jitter_factor: float | None = None,
|
527
|
-
retry_exceptions: tuple | list | None = None,
|
528
|
-
as_job: bool = False,
|
529
|
-
base_dir: str | None = None,
|
530
|
-
storage_options: dict = {},
|
531
|
-
fs: AbstractFileSystem | None = None,
|
532
|
-
background: bool = False,
|
533
|
-
qos: int = 2,
|
534
|
-
config_hook: Callable[[bytes, str], dict] | None = None,
|
535
|
-
on_success: Callable | tuple[Callable, tuple | None, dict | None] | None = None,
|
536
|
-
on_failure: Callable | tuple[Callable, tuple | None, dict | None] | None = None,
|
537
|
-
on_success_pipeline: Callable
|
538
|
-
| tuple[Callable, tuple | None, dict | None]
|
539
|
-
| None = None,
|
540
|
-
on_failure_pipeline: Callable
|
541
|
-
| tuple[Callable, tuple | None, dict | None]
|
542
|
-
| None = None,
|
543
|
-
**kwargs,
|
544
|
-
):
|
545
|
-
"""
|
546
|
-
Start a pipeline listener that listens to a topic and processes the message using a pipeline.
|
547
|
-
|
548
|
-
Args:
|
549
|
-
name (str): Name of the pipeline
|
550
|
-
topic (str | None): MQTT topic to listen to
|
551
|
-
inputs (dict | None): Inputs for the pipeline
|
552
|
-
final_vars (list | None): Final variables for the pipeline
|
553
|
-
config (dict | None): Configuration for the pipeline driver
|
554
|
-
cache (bool | dict): Cache for the pipeline
|
555
|
-
executor_cfg (str | dict | ExecutorConfig | None): Executor configuration
|
556
|
-
with_adapter_cfg (dict | WithAdapterConfig | None): With adapter configuration
|
557
|
-
pipeline_adapter_cfg (dict | AdapterConfig | None): Pipeline adapter configuration
|
558
|
-
project_adapter_cfg (dict | AdapterConfig | None): Project adapter configuration
|
559
|
-
adapter (dict[str, Any] | None): Adapter configuration
|
560
|
-
reload (bool): Reload the pipeline
|
561
|
-
log_level (str | None): Log level for the pipeline
|
562
|
-
result_ttl (float | dt.timedelta): Result expiration time for the pipeline
|
563
|
-
run_in (int | str | dt.timedelta | None): Run in time for the pipeline
|
564
|
-
max_retries (int | None): Maximum number of retries for the pipeline
|
565
|
-
retry_delay (float | None): Delay between retries for the pipeline
|
566
|
-
jitter_factor (float | None): Jitter factor for the pipeline
|
567
|
-
retry_exceptions (tuple | list | None): Exceptions to retry for the pipeline
|
568
|
-
as_job (bool): Run the pipeline as a job
|
569
|
-
base_dir (str | None): Base directory for the pipeline
|
570
|
-
storage_options (dict): Storage options for the pipeline
|
571
|
-
fs (AbstractFileSystem | None): File system for the pipeline
|
572
|
-
background (bool): Run the listener in the background
|
573
|
-
qos (int): Quality of Service for the MQTT client
|
574
|
-
config_hook (Callable[[bytes, str], dict] | None): Hook function to modify the configuration of the pipeline
|
575
|
-
on_success (Callable | tuple[Callable, tuple | None, dict | None] | None): Callback function for successful job creation
|
576
|
-
on_failure (Callable | tuple[Callable, tuple | None, dict | None] | None): Callback function for failed job creation
|
577
|
-
on_success_pipeline (Callable | tuple[Callable, tuple | None, dict | None] | None): Callback function for successful pipeline run
|
578
|
-
on_failure_pipeline (Callable | tuple[Callable, tuple | None, dict | None] | None): Callback function for failed pipeline run
|
579
|
-
**kwargs: Additional keyword arguments
|
580
|
-
|
581
|
-
Returns:
|
582
|
-
None
|
583
|
-
|
584
|
-
Raises:
|
585
|
-
ValueError: If the config_hook is not callable
|
586
|
-
|
587
|
-
Example:
|
588
|
-
```python
|
589
|
-
from flowerpower.plugins.mqtt import MqttManager
|
590
|
-
mqtt = MqttManager()
|
591
|
-
mqtt.run_pipeline_on_message(
|
592
|
-
name="my_pipeline",
|
593
|
-
topic="my_topic",
|
594
|
-
inputs={"key": "value"},
|
595
|
-
config={"param": "value"},
|
596
|
-
as_job=True,
|
597
|
-
)
|
598
|
-
```
|
599
|
-
"""
|
600
|
-
|
601
|
-
if inputs is None:
|
602
|
-
inputs = {}
|
603
|
-
|
604
|
-
if config is None:
|
605
|
-
config = {}
|
606
|
-
|
607
|
-
if config_hook is not None and not callable(config_hook):
|
608
|
-
raise ValueError("config_hook must be a callable function")
|
609
|
-
|
610
|
-
def on_message(client, userdata, msg):
|
611
|
-
# logger.info(f"Received message on topic {topic}")
|
612
|
-
logger.info(
|
613
|
-
f"Received message on subscribed topic {topic} (exact topic {msg.topic})"
|
614
|
-
)
|
615
|
-
|
616
|
-
inputs["payload"] = msg.payload
|
617
|
-
inputs["topic"] = msg.topic
|
618
|
-
|
619
|
-
if config_hook is not None:
|
620
|
-
# config_ = config_hook(inputs["payload"], inputs["topic"])
|
621
|
-
try:
|
622
|
-
config_ = config_hook(inputs["payload"], inputs["topic"])
|
623
|
-
logger.debug(f"Config from hook: {config_}")
|
624
|
-
except Exception as e:
|
625
|
-
# _ = e
|
626
|
-
logger.warning("Config hook failed. Aborting Message processing")
|
627
|
-
logger.exception(e)
|
628
|
-
return
|
629
|
-
|
630
|
-
if any([k in config_ for k in config.keys()]):
|
631
|
-
logger.warning("Config from hook overwrites config from pipeline")
|
632
|
-
|
633
|
-
config.update(config_)
|
634
|
-
logger.debug(f"Config after update: {config}")
|
635
|
-
|
636
|
-
with PipelineManager(
|
637
|
-
storage_options=storage_options, fs=fs, base_dir=base_dir
|
638
|
-
) as pipeline:
|
639
|
-
if as_job:
|
640
|
-
pipeline.add_job(
|
641
|
-
name=name,
|
642
|
-
inputs=inputs,
|
643
|
-
final_vars=final_vars,
|
644
|
-
config=config,
|
645
|
-
cache=cache,
|
646
|
-
executor_cfg=executor_cfg,
|
647
|
-
with_adapter_cfg=with_adapter_cfg,
|
648
|
-
pipeline_adapter_cfg=pipeline_adapter_cfg,
|
649
|
-
project_adapter_cfg=project_adapter_cfg,
|
650
|
-
adapter=adapter,
|
651
|
-
run_in=run_in,
|
652
|
-
reload=reload,
|
653
|
-
log_level=log_level,
|
654
|
-
result_ttl=result_ttl,
|
655
|
-
max_retries=max_retries,
|
656
|
-
retry_delay=retry_delay,
|
657
|
-
jitter_factor=jitter_factor,
|
658
|
-
retry_exceptions=retry_exceptions,
|
659
|
-
on_failure=on_failure,
|
660
|
-
on_success=on_success,
|
661
|
-
on_failure_pipeline=on_failure_pipeline,
|
662
|
-
on_success_pipeline=on_success_pipeline,
|
663
|
-
**kwargs,
|
664
|
-
)
|
665
|
-
|
666
|
-
else:
|
667
|
-
pipeline.run(
|
668
|
-
name=name,
|
669
|
-
inputs=inputs,
|
670
|
-
final_vars=final_vars,
|
671
|
-
config=config,
|
672
|
-
cache=cache,
|
673
|
-
executor_cfg=executor_cfg,
|
674
|
-
with_adapter_cfg=with_adapter_cfg,
|
675
|
-
pipeline_adapter_cfg=pipeline_adapter_cfg,
|
676
|
-
project_adapter_cfg=project_adapter_cfg,
|
677
|
-
adapter=adapter,
|
678
|
-
reload=reload,
|
679
|
-
log_level=log_level,
|
680
|
-
max_retries=max_retries,
|
681
|
-
retry_delay=retry_delay,
|
682
|
-
jitter_factor=jitter_factor,
|
683
|
-
retry_exceptions=retry_exceptions,
|
684
|
-
on_failure=on_failure_pipeline,
|
685
|
-
on_success=on_success_pipeline,
|
686
|
-
)
|
687
|
-
|
688
|
-
self.start_listener(
|
689
|
-
on_message=on_message, topic=topic, background=background, qos=qos
|
690
|
-
)
|
691
|
-
|
692
|
-
|
693
|
-
def start_listener(
|
694
|
-
on_message: Callable,
|
695
|
-
topic: str | None = None,
|
696
|
-
background: bool = False,
|
697
|
-
mqtt_cfg: dict | MqttConfig = {},
|
698
|
-
base_dir: str | None = None,
|
699
|
-
username: str | None = None,
|
700
|
-
password: str | None = None,
|
701
|
-
host: str | None = None,
|
702
|
-
port: int | None = None,
|
703
|
-
clean_session: bool = True,
|
704
|
-
qos: int = 2,
|
705
|
-
client_id: str | None = None,
|
706
|
-
client_id_suffix: str | None = None,
|
707
|
-
config_hook: Callable[[bytes, str], dict] | None = None,
|
708
|
-
**kwargs,
|
709
|
-
) -> None:
|
710
|
-
"""
|
711
|
-
Start the MQTT listener.
|
712
|
-
|
713
|
-
The connection to the MQTT broker is established using the provided configuration of a
|
714
|
-
MQTT event broker defined in the project configuration file `conf/project.toml`.
|
715
|
-
If no configuration is found, you have to provide either the argument `mqtt_cfg`, dict with the
|
716
|
-
connection parameters or the arguments `username`, `password`, `host`, and `port`.
|
717
|
-
|
718
|
-
Args:
|
719
|
-
on_message (Callable): Callback function to run when a message is received
|
720
|
-
topic (str | None): MQTT topic to listen to
|
721
|
-
background (bool): Run the listener in the background
|
722
|
-
mqtt_cfg (dict | MqttConfig): MQTT client configuration. Use either this or arguments
|
723
|
-
username, password, host, and port.
|
724
|
-
base_dir (str | None): Base directory for the module
|
725
|
-
username (str | None): Username for the MQTT client
|
726
|
-
password (str | None): Password for the MQTT client
|
727
|
-
host (str | None): Host for the MQTT client
|
728
|
-
port (int | None): Port for the MQTT client
|
729
|
-
clean_session (bool): Clean session flag for the MQTT client
|
730
|
-
qos (int): Quality of Service for the MQTT client
|
731
|
-
client_id (str | None): Client ID for the MQTT client
|
732
|
-
client_id_suffix (str | None): Client ID suffix for the MQTT client
|
733
|
-
config_hook (Callable[[bytes, str], dict] | None): Hook function to modify the configuration of the pipeline
|
734
|
-
**kwargs: Additional keyword arguments
|
735
|
-
|
736
|
-
Returns:
|
737
|
-
None
|
738
|
-
|
739
|
-
Raises:
|
740
|
-
ValueError: If the config_hook is not callable
|
741
|
-
ValueError: If no client configuration is found
|
742
|
-
|
743
|
-
Example:
|
744
|
-
```python
|
745
|
-
from flowerpower.plugins.mqtt import start_listener
|
746
|
-
|
747
|
-
start_listener(
|
748
|
-
on_message=my_on_message_function,
|
749
|
-
topic="my_topic",
|
750
|
-
background=True,
|
751
|
-
mqtt_cfg={"host": "localhost", "port": 1883},
|
752
|
-
)
|
753
|
-
```
|
754
|
-
"""
|
755
|
-
try:
|
756
|
-
client = MqttManager.from_event_broker(base_dir)
|
757
|
-
except ValueError:
|
758
|
-
if mqtt_cfg:
|
759
|
-
if isinstance(mqtt_cfg, MqttConfig):
|
760
|
-
client = MqttManager.from_config(mqtt_cfg)
|
761
|
-
elif isinstance(mqtt_cfg, dict):
|
762
|
-
client = MqttManager.from_dict(mqtt_cfg)
|
763
|
-
elif host and port:
|
764
|
-
client = MqttManager(
|
765
|
-
username=username,
|
766
|
-
password=password,
|
767
|
-
host=host,
|
768
|
-
port=port,
|
769
|
-
clean_session=clean_session,
|
770
|
-
client_id=client_id,
|
771
|
-
client_id_suffix=client_id_suffix,
|
772
|
-
config_hook=config_hook,
|
773
|
-
**kwargs,
|
774
|
-
)
|
775
|
-
else:
|
776
|
-
raise ValueError(
|
777
|
-
"No client configuration found. Please provide a client configuration "
|
778
|
-
"or a FlowerPower project base directory, in which a event broker is "
|
779
|
-
"configured in the `config/project.yml` file."
|
780
|
-
)
|
781
|
-
|
782
|
-
client.start_listener(
|
783
|
-
on_message=on_message, topic=topic, background=background, qos=qos
|
784
|
-
)
|
785
|
-
|
786
|
-
|
787
|
-
def run_pipeline_on_message(
|
788
|
-
name: str,
|
789
|
-
topic: str | None = None,
|
790
|
-
inputs: dict | None = None,
|
791
|
-
final_vars: list | None = None,
|
792
|
-
config: dict | None = None,
|
793
|
-
cache: bool | dict = False,
|
794
|
-
executor_cfg: str | dict | ExecutorConfig | None = None,
|
795
|
-
with_adapter_cfg: dict | WithAdapterConfig | None = None,
|
796
|
-
pipeline_adapter_cfg: dict | AdapterConfig | None = None,
|
797
|
-
project_adapter_cfg: dict | AdapterConfig | None = None,
|
798
|
-
adapter: dict[str, Any] | None = None,
|
799
|
-
reload: bool = False,
|
800
|
-
log_level: str | None = None,
|
801
|
-
result_ttl: float | dt.timedelta = 0,
|
802
|
-
run_in: int | str | dt.timedelta | None = None,
|
803
|
-
max_retries: int | None = None,
|
804
|
-
retry_delay: float | None = None,
|
805
|
-
jitter_factor: float | None = None,
|
806
|
-
retry_exceptions: tuple | list | None = None,
|
807
|
-
as_job: bool = False,
|
808
|
-
base_dir: str | None = None,
|
809
|
-
storage_options: dict = {},
|
810
|
-
fs: AbstractFileSystem | None = None,
|
811
|
-
background: bool = False,
|
812
|
-
mqtt_cfg: dict | MqttConfig = {},
|
813
|
-
host: str | None = None,
|
814
|
-
port: int | None = None,
|
815
|
-
username: str | None = None,
|
816
|
-
password: str | None = None,
|
817
|
-
clean_session: bool = True,
|
818
|
-
qos: int = 2,
|
819
|
-
client_id: str | None = None,
|
820
|
-
client_id_suffix: str | None = None,
|
821
|
-
config_hook: Callable[[bytes, str], dict] | None = None,
|
822
|
-
**kwargs,
|
823
|
-
):
|
824
|
-
"""
|
825
|
-
Start a pipeline listener that listens to a topic and processes the message using a pipeline.
|
826
|
-
|
827
|
-
Args:
|
828
|
-
name (str): Name of the pipeline
|
829
|
-
topic (str | None): MQTT topic to listen to
|
830
|
-
inputs (dict | None): Inputs for the pipeline
|
831
|
-
final_vars (list | None): Final variables for the pipeline
|
832
|
-
config (dict | None): Configuration for the pipeline driver
|
833
|
-
cache (bool | dict): Cache for the pipeline
|
834
|
-
executor_cfg (str | dict | ExecutorConfig | None): Executor configuration
|
835
|
-
with_adapter_cfg (dict | WithAdapterConfig | None): With adapter configuration
|
836
|
-
pipeline_adapter_cfg (dict | AdapterConfig | None): Pipeline adapter configuration
|
837
|
-
project_adapter_cfg (dict | AdapterConfig | None): Project adapter configuration
|
838
|
-
adapter (dict[str, Any] | None): Adapter configuration
|
839
|
-
reload (bool): Reload the pipeline
|
840
|
-
log_level (str | None): Log level for the pipeline
|
841
|
-
result_ttl (float | dt.timedelta): Result expiration time for the pipeline
|
842
|
-
run_in (int | str | dt.timedelta | None): Run in time for the pipeline
|
843
|
-
max_retries (int | None): Maximum number of retries for the pipeline
|
844
|
-
retry_delay (float | None): Delay between retries for the pipeline
|
845
|
-
jitter_factor (float | None): Jitter factor for the pipeline
|
846
|
-
retry_exceptions (tuple | list | None): Exceptions to retry for the pipeline
|
847
|
-
as_job (bool): Run the pipeline as a job
|
848
|
-
base_dir (str | None): Base directory for the pipeline
|
849
|
-
storage_options (dict): Storage options for the pipeline
|
850
|
-
fs (AbstractFileSystem | None): File system for the pipeline
|
851
|
-
background (bool): Run the listener in the background
|
852
|
-
mqtt_cfg (dict | MqttConfig): MQTT client configuration. Use either this or arguments
|
853
|
-
username, password, host, and port.
|
854
|
-
host (str | None): Host for the MQTT client
|
855
|
-
port (int | None): Port for the MQTT client
|
856
|
-
username (str | None): Username for the MQTT client
|
857
|
-
password (str | None): Password for the MQTT client
|
858
|
-
clean_session (bool): Clean session flag for the MQTT client
|
859
|
-
qos (int): Quality of Service for the MQTT client
|
860
|
-
client_id (str | None): Client ID for the MQTT client
|
861
|
-
client_id_suffix (str | None): Client ID suffix for the MQTT client
|
862
|
-
config_hook (Callable[[bytes, str], dict] | None): Hook function to modify the configuration of the pipeline
|
863
|
-
**kwargs: Additional keyword arguments
|
864
|
-
|
865
|
-
Returns:
|
866
|
-
None
|
867
|
-
|
868
|
-
Raises:
|
869
|
-
ValueError: If the config_hook is not callable
|
870
|
-
ValueError: If no client configuration is found
|
871
|
-
|
872
|
-
Example:
|
873
|
-
```python
|
874
|
-
from flowerpower.plugins.mqtt import run_pipeline_on_message
|
875
|
-
|
876
|
-
run_pipeline_on_message(
|
877
|
-
name="my_pipeline",
|
878
|
-
topic="my_topic",
|
879
|
-
inputs={"key": "value"},
|
880
|
-
config={"param": "value"},
|
881
|
-
as_job=True,
|
882
|
-
)
|
883
|
-
```
|
884
|
-
"""
|
885
|
-
try:
|
886
|
-
client = MqttManager.from_event_broker(base_dir)
|
887
|
-
except ValueError:
|
888
|
-
if mqtt_cfg:
|
889
|
-
if isinstance(mqtt_cfg, MqttConfig):
|
890
|
-
client = MqttManager.from_config(mqtt_cfg)
|
891
|
-
elif isinstance(mqtt_cfg, dict):
|
892
|
-
client = MqttManager.from_dict(mqtt_cfg)
|
893
|
-
elif host and port:
|
894
|
-
client = MqttManager(
|
895
|
-
username=username,
|
896
|
-
password=password,
|
897
|
-
host=host,
|
898
|
-
port=port,
|
899
|
-
clean_session=clean_session,
|
900
|
-
client_id=client_id,
|
901
|
-
client_id_suffix=client_id_suffix,
|
902
|
-
config_hook=config_hook,
|
903
|
-
**kwargs,
|
904
|
-
)
|
905
|
-
else:
|
906
|
-
raise ValueError(
|
907
|
-
"No client configuration found. Please provide a client configuration "
|
908
|
-
"or a FlowerPower project base directory, in which a event broker is "
|
909
|
-
"configured in the `config/project.yml` file."
|
910
|
-
)
|
911
|
-
|
912
|
-
if client._client_id is None and client_id is not None:
|
913
|
-
client._client_id = client_id
|
914
|
-
|
915
|
-
if client._client_id_suffix is None and client_id_suffix is not None:
|
916
|
-
client._client_id_suffix = client_id_suffix
|
917
|
-
|
918
|
-
"""
|
919
|
-
cli_clean_session | config_clean_session | result
|
920
|
-
TRUE TRUE TRUE
|
921
|
-
FALSE FALSE FALSE
|
922
|
-
FALSE TRUE FALSE
|
923
|
-
TRUE FALSE FALSE
|
924
|
-
|
925
|
-
Clean session should only use default value if neither cli nor config source says otherwise
|
926
|
-
"""
|
927
|
-
client._clean_session = client._clean_session and clean_session
|
928
|
-
|
929
|
-
if client.topic is None and topic is not None:
|
930
|
-
client.topic = topic
|
931
|
-
|
932
|
-
client.run_pipeline_on_message(
|
933
|
-
name=name,
|
934
|
-
topic=topic,
|
935
|
-
inputs=inputs,
|
936
|
-
final_vars=final_vars,
|
937
|
-
config=config,
|
938
|
-
cache=cache,
|
939
|
-
executor_cfg=executor_cfg,
|
940
|
-
with_adapter_cfg=with_adapter_cfg,
|
941
|
-
pipeline_adapter_cfg=pipeline_adapter_cfg,
|
942
|
-
project_adapter_cfg=project_adapter_cfg,
|
943
|
-
adapter=adapter,
|
944
|
-
reload=reload,
|
945
|
-
log_level=log_level,
|
946
|
-
result_ttl=result_ttl,
|
947
|
-
run_in=run_in,
|
948
|
-
max_retries=max_retries,
|
949
|
-
retry_delay=retry_delay,
|
950
|
-
jitter_factor=jitter_factor,
|
951
|
-
retry_exceptions=retry_exceptions,
|
952
|
-
as_job=as_job,
|
953
|
-
base_dir=base_dir,
|
954
|
-
storage_options=storage_options,
|
955
|
-
fs=fs,
|
956
|
-
background=background,
|
957
|
-
qos=qos,
|
958
|
-
client_id=client_id,
|
959
|
-
client_id_suffix=client_id_suffix,
|
960
|
-
config_hook=config_hook,
|
961
|
-
**kwargs,
|
962
|
-
)
|