Files
tradon/modules/web_shop_shopify/shopify_retry.py
2026-03-14 09:42:12 +00:00

88 lines
3.1 KiB
Python

# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import json
import logging
import time
import urllib
from pyactiveresource.connection import ClientError
from shopify import Limits
from shopify.base import ShopifyConnection
from shopify.resources.graphql import GraphQL
try:
from shopify.resources.graphql import GraphQLException
except ImportError:
class GraphQLException(Exception):
def __init__(self, response):
self._response = response
@property
def errors(self):
return self._response['errors']
from trytond.protocols.wrappers import HTTPStatus
from trytond.tools.logging import format_args
logger = logging.getLogger(__name__)
def patch():
def _open(*args, **kwargs):
while True:
try:
return open_func(*args, **kwargs)
except ClientError as e:
if e.response.code == HTTPStatus.TOO_MANY_REQUESTS:
retry_after = float(
e.response.headers.get('Retry-After', 2))
logger.debug(
"Shopify connection retry after %ss", retry_after)
time.sleep(retry_after)
else:
raise
else:
try:
if Limits.credit_maxed():
logger.debug("Shopify connection credit maxed")
time.sleep(0.5)
except Exception:
pass
if ShopifyConnection._open != _open:
open_func = ShopifyConnection._open
ShopifyConnection._open = _open
def graphql_execute(self, *args, **kwargs):
log_message = "GraphQL execute %s"
log_args = (
format_args(args, kwargs, logger.isEnabledFor(logging.DEBUG)),)
while True:
try:
result = graphql_execute_func(self, *args, **kwargs)
except urllib.error.HTTPError as e:
if e.code == HTTPStatus.TOO_MANY_REQUESTS:
retry_after = float(e.headers.get('Retry-After', 2))
logger.debug("GraphQL retry after %ss", retry_after)
time.sleep(retry_after)
else:
logger.exception(log_message, *log_args)
raise GraphQLException(json.load(e.fp))
if isinstance(result, str):
result = json.loads(result)
if result.get('errors'):
for error in result['errors']:
if error.get('extensions', {}).get('code') == 'THROTTLED':
logger.debug("GraphQL throttled")
time.sleep(0.5)
continue
logger.exception(log_message, *log_args)
raise GraphQLException(result)
logger.info(log_message, *log_args)
logger.debug("GraphQL Result: %r", result)
return result
if GraphQL.execute != graphql_execute:
graphql_execute_func = GraphQL.execute
GraphQL.execute = graphql_execute