RAPTOR v18.4: Исправлена отчетность, активированы выходные
This commit is contained in:
21
invest-python-master/t_tech/invest/retrying/aio/client.py
Normal file
21
invest-python-master/t_tech/invest/retrying/aio/client.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from t_tech.invest import AsyncClient
|
||||
from t_tech.invest.retrying.aio.grpc_interceptor import AsyncRetryClientInterceptor
|
||||
from t_tech.invest.retrying.aio.retry_manager import AsyncRetryManager
|
||||
from t_tech.invest.retrying.settings_protocol import RetryClientSettingsProtocol
|
||||
|
||||
|
||||
class AsyncRetryingClient(AsyncClient):
|
||||
def __init__(
|
||||
self,
|
||||
token: str,
|
||||
settings: RetryClientSettingsProtocol,
|
||||
**kwargs,
|
||||
):
|
||||
self._retry_manager = AsyncRetryManager(settings=settings)
|
||||
self._retry_interceptor = AsyncRetryClientInterceptor(
|
||||
retry_manager=self._retry_manager
|
||||
)
|
||||
interceptors = kwargs.get("interceptors", [])
|
||||
interceptors.append(self._retry_interceptor)
|
||||
kwargs["interceptors"] = interceptors
|
||||
super().__init__(token, **kwargs)
|
||||
@@ -0,0 +1,21 @@
|
||||
import grpc
|
||||
|
||||
from t_tech.invest.retrying.aio.retry_manager import AsyncRetryManager
|
||||
|
||||
|
||||
class AsyncRetryClientInterceptor(grpc.aio.UnaryUnaryClientInterceptor):
|
||||
def __init__(
|
||||
self, retry_manager: AsyncRetryManager
|
||||
): # pylint: disable=super-init-not-called
|
||||
self._retry_manager = retry_manager
|
||||
|
||||
async def _intercept_with_retry(self, continuation, client_call_details, request):
|
||||
async def call():
|
||||
return await continuation(client_call_details, request)
|
||||
|
||||
return await self._retry_manager.call_with_retries(call=call)
|
||||
|
||||
async def intercept_unary_unary(self, continuation, client_call_details, request):
|
||||
return await self._intercept_with_retry(
|
||||
continuation, client_call_details, request
|
||||
)
|
||||
@@ -0,0 +1,35 @@
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from grpc.aio import AioRpcError
|
||||
|
||||
from t_tech.invest.logging import get_metadata_from_aio_error
|
||||
from t_tech.invest.retrying.base_retry_manager import BaseRetryManager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AsyncRetryManager(BaseRetryManager):
|
||||
async def call_with_retries(self, call: Any):
|
||||
retries_left = self.get_initial_retries()
|
||||
while retries_left > 0:
|
||||
logger.debug("Trying to call")
|
||||
response = await call()
|
||||
try:
|
||||
await response
|
||||
logger.debug("Call succeeded")
|
||||
return response
|
||||
except AioRpcError as exception:
|
||||
retries_left -= 1
|
||||
logger.debug("Retries left = %s", retries_left)
|
||||
|
||||
metadata = get_metadata_from_aio_error(exception)
|
||||
seconds_to_sleep = self.extract_seconds_to_sleep(metadata)
|
||||
await self._sleep(seconds_to_sleep)
|
||||
|
||||
logger.debug("RetryManager exhausted, no retries left")
|
||||
return response
|
||||
|
||||
async def _sleep(self, seconds_to_sleep):
|
||||
await asyncio.sleep(seconds_to_sleep)
|
||||
@@ -0,0 +1,25 @@
|
||||
import logging
|
||||
|
||||
from t_tech.invest.retrying.settings_protocol import RetryClientSettingsProtocol
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BaseRetryManager:
|
||||
def __init__(self, settings: RetryClientSettingsProtocol):
|
||||
self._settings = settings
|
||||
|
||||
def get_initial_retries(self):
|
||||
retries_left = self._settings.max_retry_attempt
|
||||
if not self._settings.use_retry:
|
||||
retries_left = 0
|
||||
logger.debug("Retrying disabled")
|
||||
retries_left += 1
|
||||
return retries_left
|
||||
|
||||
@staticmethod
|
||||
def extract_seconds_to_sleep(metadata) -> int:
|
||||
logger.debug("Received metadata %s", metadata)
|
||||
seconds_to_sleep = metadata.ratelimit_reset
|
||||
logger.debug("Sleeping for %s seconds", seconds_to_sleep)
|
||||
return seconds_to_sleep
|
||||
9
invest-python-master/t_tech/invest/retrying/settings.py
Normal file
9
invest-python-master/t_tech/invest/retrying/settings.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import dataclasses
|
||||
|
||||
from t_tech.invest.retrying.settings_protocol import RetryClientSettingsProtocol
|
||||
|
||||
|
||||
@dataclasses.dataclass()
|
||||
class RetryClientSettings(RetryClientSettingsProtocol):
|
||||
use_retry: bool = True
|
||||
max_retry_attempt: int = 3
|
||||
@@ -0,0 +1,6 @@
|
||||
from typing import Protocol
|
||||
|
||||
|
||||
class RetryClientSettingsProtocol(Protocol):
|
||||
use_retry: bool
|
||||
max_retry_attempt: int
|
||||
21
invest-python-master/t_tech/invest/retrying/sync/client.py
Normal file
21
invest-python-master/t_tech/invest/retrying/sync/client.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from t_tech.invest import Client
|
||||
from t_tech.invest.retrying.settings_protocol import RetryClientSettingsProtocol
|
||||
from t_tech.invest.retrying.sync.grpc_interceptor import RetryClientInterceptor
|
||||
from t_tech.invest.retrying.sync.retry_manager import RetryManager
|
||||
|
||||
|
||||
class RetryingClient(Client):
|
||||
def __init__(
|
||||
self,
|
||||
token: str,
|
||||
settings: RetryClientSettingsProtocol,
|
||||
**kwargs,
|
||||
):
|
||||
self._retry_manager = RetryManager(settings=settings)
|
||||
self._retry_interceptor = RetryClientInterceptor(
|
||||
retry_manager=self._retry_manager
|
||||
)
|
||||
interceptors = kwargs.get("interceptors", [])
|
||||
interceptors.append(self._retry_interceptor)
|
||||
kwargs["interceptors"] = interceptors
|
||||
super().__init__(token, **kwargs)
|
||||
@@ -0,0 +1,19 @@
|
||||
import grpc
|
||||
|
||||
from t_tech.invest.retrying.sync.retry_manager import RetryManager
|
||||
|
||||
|
||||
class RetryClientInterceptor(grpc.UnaryUnaryClientInterceptor):
|
||||
def __init__(
|
||||
self, retry_manager: RetryManager
|
||||
): # pylint: disable=super-init-not-called
|
||||
self._retry_manager = retry_manager
|
||||
|
||||
def _intercept_with_retry(self, continuation, client_call_details, request):
|
||||
def call():
|
||||
return continuation(client_call_details, request)
|
||||
|
||||
return self._retry_manager.call_with_retries(call=call)
|
||||
|
||||
def intercept_unary_unary(self, continuation, client_call_details, request):
|
||||
return self._intercept_with_retry(continuation, client_call_details, request)
|
||||
@@ -0,0 +1,31 @@
|
||||
import logging
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
from t_tech.invest.logging import get_metadata_from_call
|
||||
from t_tech.invest.retrying.base_retry_manager import BaseRetryManager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RetryManager(BaseRetryManager):
|
||||
def call_with_retries(self, call: Any):
|
||||
retries_left = self.get_initial_retries()
|
||||
while retries_left > 0:
|
||||
logger.debug("Trying to call")
|
||||
result = call()
|
||||
logger.debug("Call succeeded")
|
||||
exception = result.exception()
|
||||
if not exception:
|
||||
return result
|
||||
retries_left -= 1
|
||||
logger.debug("Retries left = %s", retries_left)
|
||||
metadata = get_metadata_from_call(exception)
|
||||
seconds_to_sleep = self.extract_seconds_to_sleep(metadata)
|
||||
self._sleep(seconds_to_sleep)
|
||||
|
||||
logger.debug("RetryManager exhausted, no retries left")
|
||||
return result
|
||||
|
||||
def _sleep(self, seconds_to_sleep):
|
||||
time.sleep(seconds_to_sleep)
|
||||
Reference in New Issue
Block a user