scalable-pypeline 2.1.22__py2.py3-none-any.whl → 2.1.23__py2.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.
pypeline/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "2.1.22"
1
+ __version__ = "2.1.23"
pypeline/constants.py CHANGED
@@ -1,5 +1,4 @@
1
- """ Pypeline Constants
2
- """
1
+ """Pypeline Constants"""
3
2
 
4
3
  import os
5
4
 
@@ -15,6 +14,7 @@ DEFAULT_BROKER_CALLABLE = os.environ.get(
15
14
  # Pypeline broker connections
16
15
  RABBIT_URL = os.environ.get("RABBIT_URL", "amqp://admin:password@127.0.0.1:5672")
17
16
  REDIS_URL = os.environ.get("REDIS_URL", "redis://localhost:6379/0")
17
+ REDIS_SENTINAL_MASTER_NAME = os.environ.get("REDIS_SENTINAL_MASTER_NAME", None)
18
18
 
19
19
  # Pypeline task defaults
20
20
  PARALLEL_PIPELINE_CALLBACK_BARRIER_TTL = int(
@@ -39,6 +39,16 @@ DEFAULT_BROKER_BLOCKED_CONNECTION_TIMEOUT = int(
39
39
  DEFAULT_BROKER_HEARTBEAT_TIMEOUT = int(
40
40
  os.getenv("DEFAULT_BROKER_HEARTBEAT_TIMEOUT", 300000)
41
41
  )
42
+ DEFAULT_REDIS_SOCKET_CONNECT_TIMEOUT = int(
43
+ os.getenv("DEFAULT_REDIS_SOCKET_CONNECT_TIMEOUT", 1)
44
+ )
45
+ DEFAULT_REDIS_SOCKET_TIMEOUT = int(os.getenv("DEFAULT_REDIS_SOCKET_TIMEOUT", 2))
46
+ DEFAULT_REDIS_RETRY_ON_TIMEOUT = bool(os.getenv("DEFAULT_REDIS_RETRY_ON_TIMEOUT", True))
47
+ DEFAULT_REDIS_SOCKET_KEEPALIVE = bool(os.getenv("DEFAULT_REDIS_SOCKET_KEEPALIVE", True))
48
+ DEFAULT_REDIS_HEALTH_CHECK_INTERVAL = int(
49
+ os.getenv("DEFAULT_REDIS_HEALTH_CHECK_INTERVAL", 30)
50
+ )
51
+
42
52
  MESSAGE_BROKER = os.getenv("MESSAGE_BROKER", "RABBITMQ")
43
53
 
44
54
  MS_IN_SECONDS = 1000
pypeline/dramatiq.py CHANGED
@@ -8,7 +8,7 @@ import click
8
8
  from urllib.parse import urlparse
9
9
 
10
10
  from dramatiq.brokers.redis import RedisBroker
11
-
11
+ from redis.sentinel import Sentinel
12
12
  from pypeline.extensions import pypeline_config
13
13
  from warnings import warn
14
14
  from apscheduler.schedulers.blocking import BlockingScheduler
@@ -30,6 +30,7 @@ from flask.cli import with_appcontext
30
30
 
31
31
  from pypeline.constants import (
32
32
  REDIS_URL,
33
+ REDIS_SENTINAL_MASTER_NAME,
33
34
  RABBIT_URL,
34
35
  DEFAULT_BROKER_CALLABLE,
35
36
  DEFAULT_BROKER_CONNECTION_HEARTBEAT,
@@ -37,6 +38,11 @@ from pypeline.constants import (
37
38
  DEFAULT_BROKER_CONNECTION_ATTEMPTS,
38
39
  MESSAGE_BROKER,
39
40
  DEFAULT_BROKER_HEARTBEAT_TIMEOUT,
41
+ DEFAULT_REDIS_SOCKET_CONNECT_TIMEOUT,
42
+ DEFAULT_REDIS_SOCKET_TIMEOUT,
43
+ DEFAULT_REDIS_RETRY_ON_TIMEOUT,
44
+ DEFAULT_REDIS_SOCKET_KEEPALIVE,
45
+ DEFAULT_REDIS_HEALTH_CHECK_INTERVAL,
40
46
  )
41
47
  from pypeline.pipelines.middleware.get_active_worker_id_middleware import (
42
48
  GetActiveWorkerIdMiddleware,
@@ -45,7 +51,8 @@ from pypeline.pipelines.middleware.parallel_pipeline_middleware import ParallelP
45
51
  from pypeline.pipelines.middleware.pypeline_middleware import PypelineMiddleware
46
52
  from pypeline.utils.config_utils import (
47
53
  retrieve_latest_schedule_config,
48
- get_service_config_for_worker, retrieve_executable_job_config,
54
+ get_service_config_for_worker,
55
+ retrieve_executable_job_config,
49
56
  )
50
57
  from pypeline.utils.dramatiq_utils import (
51
58
  guess_code_directory,
@@ -62,7 +69,23 @@ logger = logging.getLogger(__name__)
62
69
 
63
70
 
64
71
  def configure_default_broker(broker: Broker = None):
65
- redis_backend = RedisBackend(url=REDIS_URL)
72
+ redis_client = None
73
+ if REDIS_SENTINAL_MASTER_NAME is not None:
74
+ parsed_redis_url = urlparse(REDIS_URL)
75
+ redis_sentinel = Sentinel(
76
+ sentinels=[(parsed_redis_url.hostname, parsed_redis_url.port)],
77
+ )
78
+ redis_client = redis_sentinel.master_for(
79
+ REDIS_SENTINAL_MASTER_NAME,
80
+ db=int(parsed_redis_url.path[1]) if parsed_redis_url.path else 0,
81
+ password=parsed_redis_url.password,
82
+ socket_connect_timeout=DEFAULT_REDIS_SOCKET_CONNECT_TIMEOUT,
83
+ socket_timeout=DEFAULT_REDIS_SOCKET_TIMEOUT,
84
+ retry_on_timeout=DEFAULT_REDIS_RETRY_ON_TIMEOUT,
85
+ socket_keepalive=DEFAULT_REDIS_SOCKET_KEEPALIVE,
86
+ health_check_interval=DEFAULT_REDIS_HEALTH_CHECK_INTERVAL,
87
+ )
88
+ redis_backend = RedisBackend(client=redis_client, url=REDIS_URL)
66
89
 
67
90
  if MESSAGE_BROKER == "RABBITMQ":
68
91
  parsed_url = urlparse(RABBIT_URL)
@@ -85,7 +108,9 @@ def configure_default_broker(broker: Broker = None):
85
108
  broker
86
109
  if broker is not None
87
110
  else RedisBroker(
88
- url=REDIS_URL, heartbeat_timeout=DEFAULT_BROKER_HEARTBEAT_TIMEOUT
111
+ client=redis_client,
112
+ url=REDIS_URL,
113
+ heartbeat_timeout=DEFAULT_BROKER_HEARTBEAT_TIMEOUT,
89
114
  )
90
115
  )
91
116
 
@@ -169,7 +194,6 @@ def register_actors_for_workers(broker: Broker):
169
194
  logger.exception(f"Unable to add a task to dramatiq: {e}")
170
195
 
171
196
 
172
-
173
197
  class Dramatiq:
174
198
  """Flask extension bridging Dramatiq broker and Flask app.
175
199
 
@@ -113,11 +113,15 @@ class LazyActor(object):
113
113
  return getattr(self.actor, name)
114
114
 
115
115
  def register(self, broker):
116
- self.actor = register_actor(
117
- actor_name=f"{self.fn.__module__}.{self.fn.__name__}-{self.kw['queue_name']}",
118
- broker=broker,
119
- **self.kw,
120
- )(ensure_return_value(default_value=True)(self.fn))
116
+ actor_name = f"{self.fn.__module__}.{self.fn.__name__}-{self.kw['queue_name']}"
117
+ if actor_name in broker.actors:
118
+ self.actor = broker.actors[actor_name]
119
+ else:
120
+ self.actor = register_actor(
121
+ actor_name=actor_name,
122
+ broker=broker,
123
+ **self.kw,
124
+ )(ensure_return_value(default_value=True)(self.fn))
121
125
 
122
126
  # Next is regular actor API.
123
127
  def send(self, *a, **kw):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scalable-pypeline
3
- Version: 2.1.22
3
+ Version: 2.1.23
4
4
  Summary: PypeLine - Python pipelines for the Real World
5
5
  Home-page: https://gitlab.com/bravos2/pypeline
6
6
  Author: Bravos Power Corporation
@@ -25,7 +25,7 @@ Requires-Dist: pytest-cov (<3,>=2.6.1) ; extra == 'test'
25
25
  Requires-Dist: tox (<4,>=3.14.1) ; extra == 'test'
26
26
  Requires-Dist: mock (<2,>=1) ; extra == 'test'
27
27
  Requires-Dist: responses (<0.11,>=0.10.16) ; extra == 'test'
28
- Requires-Dist: fakeredis (<3,>=2.10.3) ; extra == 'test'
28
+ Requires-Dist: fakeredis (<2.31,>=2.10.3) ; extra == 'test'
29
29
  Provides-Extra: web
30
30
  Requires-Dist: gunicorn ; extra == 'web'
31
31
  Requires-Dist: gevent (<22,>=21.12.0) ; extra == 'web'
@@ -1,7 +1,7 @@
1
- pypeline/__init__.py,sha256=8X_w-VRCyU1lQMWejIqkf5tmhnrgO7csLi27xV88LJs,23
1
+ pypeline/__init__.py,sha256=v7ybXce2sltwQL38gMDsgF0NlBfnohuHthBrSTULxMw,23
2
2
  pypeline/barrier.py,sha256=oO964l9qOCOibweOHyNivmAvufdXOke9nz2tdgclouo,1172
3
- pypeline/constants.py,sha256=EGSuLq4KhZ4bxrbtnUgKclELRyya5ipvv0WeybCzNAs,3049
4
- pypeline/dramatiq.py,sha256=S_rZMpGgE-VAmx9YjDBkHpSjFdhwp7mz4uuuKBUx4iQ,14405
3
+ pypeline/constants.py,sha256=SLYWQ56zMQI75Imijw1z33bugcmJ5zCYfhc6uTb-w1I,3592
4
+ pypeline/dramatiq.py,sha256=ElqzpLDuNOCNrW2aw3Ml1p6_0AnwOmQ5jcl5GQ6JuFM,15527
5
5
  pypeline/executable_job_config_schema.py,sha256=P2Z8SO057Jgyt4I5oZxcbEi1iaZkLoAh7qp8PtuqcqU,1010
6
6
  pypeline/extensions.py,sha256=BzOTnXhNxap3N7uIUUh_hO6dDwx08Vc_RJDE93_K0Lo,610
7
7
  pypeline/pipeline_config_schema.py,sha256=kRZcCMlk2FIITDzVrAfcSmHnxi1mIWmDzasTW0TnaAU,11169
@@ -26,16 +26,16 @@ pypeline/pipelines/middleware/parallel_pipeline_middleware.py,sha256=kTp6niYoe2n
26
26
  pypeline/pipelines/middleware/pypeline_middleware.py,sha256=AGQCRmqXcYNyCxinwtGZplHwltrmZ_sH73CVRLu_0EE,8961
27
27
  pypeline/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  pypeline/utils/config_utils.py,sha256=bblh8clRDDNQpQIDkBrtskZBo-csakoO1IJiaqVGyr8,2508
29
- pypeline/utils/dramatiq_utils.py,sha256=DUdgVywm1182A4i69XzH9EIh1EJ9zAHmJLtOaVSW7pw,3844
29
+ pypeline/utils/dramatiq_utils.py,sha256=tbG3o5FD0zUOKtJJJECE2cM2ovDv3OLQ5CplJ9cXfM4,4001
30
30
  pypeline/utils/executable_job_util.py,sha256=Id4FYvCdzqOCzQYSoU2yeOncubKwSwITUf_BgIPZQUw,1206
31
31
  pypeline/utils/graceful_shutdown_util.py,sha256=gdyf4r_vlunZZP-prcol_9aJQEG9Hk8evivVSe_H0N0,1293
32
32
  pypeline/utils/module_utils.py,sha256=-yEJIukDCoXnmlZVXB6Dww25tH6GdPE5SoFqv6pfdVU,3682
33
33
  pypeline/utils/pipeline_utils.py,sha256=kGP1QwCJikGC5QNRtzRXCDVewyRMpWIqERTNnxGLlSY,4795
34
34
  pypeline/utils/schema_utils.py,sha256=Fgl0y9Cuo_TZeEx_S3gaSVnLjn6467LTkjb2ek7Ms98,851
35
35
  tests/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- scalable_pypeline-2.1.22.dist-info/LICENSE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174
37
- scalable_pypeline-2.1.22.dist-info/METADATA,sha256=j5IwcFIS2j3cTjCEU8uE9h3UYyC1rzkZT7v_SYc7dis,5982
38
- scalable_pypeline-2.1.22.dist-info/WHEEL,sha256=bb2Ot9scclHKMOLDEHY6B2sicWOgugjFKaJsT7vwMQo,110
39
- scalable_pypeline-2.1.22.dist-info/entry_points.txt,sha256=uWs10ODfHSBKo2Cx_QaUjPHQTpZ3e77j9VlAdRRmMyg,119
40
- scalable_pypeline-2.1.22.dist-info/top_level.txt,sha256=C7dpkEOc_-nnsAQb28BfQknjD6XHRyS9ZrvVeoIbV7s,15
41
- scalable_pypeline-2.1.22.dist-info/RECORD,,
36
+ scalable_pypeline-2.1.23.dist-info/LICENSE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174
37
+ scalable_pypeline-2.1.23.dist-info/METADATA,sha256=OdNeYdHW9jO0ILRNPcCWM-yG7CQn-GEawq02AfxUP1w,5985
38
+ scalable_pypeline-2.1.23.dist-info/WHEEL,sha256=bb2Ot9scclHKMOLDEHY6B2sicWOgugjFKaJsT7vwMQo,110
39
+ scalable_pypeline-2.1.23.dist-info/entry_points.txt,sha256=uWs10ODfHSBKo2Cx_QaUjPHQTpZ3e77j9VlAdRRmMyg,119
40
+ scalable_pypeline-2.1.23.dist-info/top_level.txt,sha256=C7dpkEOc_-nnsAQb28BfQknjD6XHRyS9ZrvVeoIbV7s,15
41
+ scalable_pypeline-2.1.23.dist-info/RECORD,,