|
54 | 54 | from shapely.geos import PredicateError, ReadingError, TopologicalError
|
55 | 55 | from flask import g
|
56 | 56 | import flask
|
| 57 | +import pybreaker |
57 | 58 | from jormungandr import georef, schedule, realtime_schedule, ptref, street_network, fallback_modes
|
58 | 59 | from jormungandr.scenarios.ridesharing.ridesharing_service_manager import RidesharingServiceManager
|
59 | 60 | import six
|
@@ -138,6 +139,10 @@ def __init__(
|
138 | 139 | self.timezone = None # timezone will be fetched from the kraken
|
139 | 140 | self.publication_date = -1
|
140 | 141 | self.is_initialized = False # kraken hasn't been called yet we don't have geom nor timezone
|
| 142 | + self.breaker = pybreaker.CircuitBreaker( |
| 143 | + fail_max=app.config.get(str('CIRCUIT_BREAKER_MAX_INSTANCE_FAIL'), 5), |
| 144 | + reset_timeout=app.config.get(str('CIRCUIT_BREAKER_INSTANCE_TIMEOUT_S'), 60), |
| 145 | + ) |
141 | 146 | self.georef = georef.Kraken(self)
|
142 | 147 | self._streetnetwork_backend_manager = streetnetwork_backend_manager
|
143 | 148 |
|
@@ -717,14 +722,21 @@ def places_proximity_radius(self):
|
717 | 722 | instance_db = self.get_models()
|
718 | 723 | return get_value_or_default('places_proximity_radius', instance_db, self.name)
|
719 | 724 |
|
720 |
| - def send_and_receive( |
721 |
| - self, request, timeout=app.config.get('INSTANCE_TIMEOUT', 10), quiet=False, request_id=None, **kwargs |
722 |
| - ): |
| 725 | + def send_and_receive(self, *args, **kwargs): |
| 726 | + """ |
| 727 | + encapsulate all call to kraken in a circuit breaker, this way we don't loose time calling dead instance |
| 728 | + """ |
| 729 | + try: |
| 730 | + return self.breaker.call(self._send_and_receive, *args, **kwargs) |
| 731 | + except pybreaker.CircuitBreakerError as e: |
| 732 | + raise DeadSocketException(self.name, self.socket_path) |
| 733 | + |
| 734 | + def _send_and_receive(self, request, timeout=app.config.get('INSTANCE_TIMEOUT', 10), quiet=False, **kwargs): |
723 | 735 | deadline = datetime.utcnow() + timedelta(milliseconds=timeout * 1000)
|
724 | 736 | request.deadline = deadline.strftime('%Y%m%dT%H%M%S,%f')
|
725 | 737 |
|
726 |
| - if request_id: |
727 |
| - request.request_id = request_id |
| 738 | + if 'request_id' in kwargs and kwargs['request_id']: |
| 739 | + request.request_id = kwargs['request_id'] |
728 | 740 | else:
|
729 | 741 | try:
|
730 | 742 | request.request_id = flask.request.id
|
@@ -839,7 +851,8 @@ def init(self):
|
839 | 851 | req.requested_api = type_pb2.METADATAS
|
840 | 852 | request_id = "instance_init"
|
841 | 853 | try:
|
842 |
| - resp = self.send_and_receive(req, request_id=request_id, timeout=1, quiet=True) |
| 854 | + # we use _send_and_receive to avoid the circuit breaker, we don't want fast fail on init :) |
| 855 | + resp = self._send_and_receive(req, request_id=request_id, timeout=1, quiet=True) |
843 | 856 | # the instance is automatically updated on a call
|
844 | 857 | if self.publication_date != pub_date:
|
845 | 858 | return True
|
|
0 commit comments