跳至主要内容

異常和重試機制

異常

ClientException

ClientException代表明確的客戶端錯誤,比如以下錯誤碼:

錯誤碼描述
SDK.SDK_INVALID_PARAMETER使用了非法的參數值,請求尚未發送到服務端之前,被檢測到錯誤
SDK.SDK_ENDPOINT_RESOLVING_ERROR找不到合適的Endpoint,無法把請求發送到服務端
SDK.SDK_INVALID_REQUEST使用了框架無法處理的Request對象

ServerException

在HTTP API的使用過程中,對於status_code != 200的請求結果,服務端會提供明確的error_code作為錯誤碼。這些失敗或者錯誤的請求,SDK會通過ServerException來表示。

ServerException的錯誤碼和原因,請參考HTTP API的服務端文檔。

重試機制

不同的業務場景,需要的重試策略很可能不一致,SDK預置了重試策略,也允許自定義擴展和設置。

HTTP API

默認機制

  1. 默認不重試
  2. 設置了重試次數後,符合條件的請求會重試,不符合條件的請求不會重試,開啟重試的代碼示例如下:
from webullsdkcore.client import ApiClient

# 設置最大重試次數為3
client = ApiClient(app_key="<your_app_key>", app_secret="<your_app_secret>", region_id="<region_id>", auto_retry=True, max_retry_num=3)

默認重試的條件判斷說明:

  1. 超過最大重試次數,不重試
  2. 不是GET請求,不重試
  3. 客戶端IOError會重試,非特定的ClientException不重試
  4. 服務端的特定錯誤碼(如下)重試,非特定錯誤碼不重試
    • TOO_MANY_REQUESTS
    • SERVICE_NOT_AVAILABLE
    • GATEWAY_TIMEOUT
    • INTERNAL_ERROR
  5. 其他錯誤和異常,不重試

行情訂閱

默認機制

  1. 默認符合條件的請求會重試,不符合條件的請求不會重試,重試的次數沒有限制,重試的時間間隔為10秒,自定義重試的代碼示例如下:
from webullsdkmdata.quotes.subscribe.default_client import DefaultQuotesClient
from webullsdkcore.retry.retry_policy import NO_RETRY_POLICY

# 設置不重試
quotes_client = DefaultQuotesClient("<your_app_key>", "<your_app_secret>", "<region_id>", retry_policy=NO_RETRY_POLICY)

默認重試的條件判斷說明:

  1. 客戶端IOError會重試,非特定的ClientException不重試
  2. mqtt協議的特定錯誤碼(如下)重試,非特定錯誤碼不重試
    • 3 (Server Unavailable)
    • 5 (Authorization error)
  3. 其他錯誤和異常,重試

交易事件檢閱/行情API

默認機制

  1. 默認符合條件的請求會重試,不符合條件的請求不會重試,重試的次數沒有限制,重試的時間間隔為10秒,自定義重試的代碼示例如下:
from webullsdktradeeventscore.events_client import EventsClient
from webullsdkcore.retry.retry_policy import NO_RETRY_POLICY

# 設置不重試
client = EventsClient("<your_app_key>", "<your_app_secret>", "<region_id>", retry_policy=NO_RETRY_POLICY)

默認重試的條件判斷說明:

  1. gRPC協議的特定錯誤碼(如下)重試,非特定錯誤碼不重試
    • 2 (UNKNOWN)
    • 13 (INTERNAL)
    • 14 (UNAVAILABLE)
  2. 其他錯誤和異常,不重試

自定義重試策略

自定義重試策略,主要通過擴展RetryPolicy來實現

RetryPolicy通過RetryCondition實現是否重試的條件判斷, 通過BackoffStrategy實現重試時間間隔的退避策略

以下代碼演示了RetryOnRcCodeCondition的實現:

# 根據MQTT協議的錯誤碼,實現的RetryCondition
class RetryOnRcCodeCondition(RetryCondition):
DEFAULT_RETRYABLE_RC_CODE_LIST = [
3,
5,
]

def __init__(self, retryable_rc_code_list=None):
if retryable_rc_code_list:
self.retryable_rc_code_list = retryable_rc_code_list
else:
self.retryable_rc_code_list = self.DEFAULT_RETRYABLE_RC_CODE_LIST

def should_retry(self, retry_policy_context):
if retry_policy_context.rc_code in self.retryable_rc_code_list:
return RetryCondition.RETRY
else:
return RetryCondition.NO_RETRY

以下代碼演示了ExponentialBackoffStrategy的實現:

# 一個簡單的指數退避策略
class ExponentialBackoffStrategy(BackoffStrategy):
MAX_RETRY_LIMIT = 30

def __init__(self, base_delay_in_milliseconds, max_delay_in_milliseconds):
self.base_delay_in_milliseconds = base_delay_in_milliseconds
self.max_delay_in_milliseconds = max_delay_in_milliseconds

def compute_delay_before_next_retry(self, retry_policy_context):
retries = min(self.MAX_RETRY_LIMIT, retry_policy_context.retries_attempted)
delay = min(self.max_delay_in_milliseconds, self.base_delay_in_milliseconds << retries)
return delay

以下代碼演示了一個簡單的RetryPolicy實現:

class MyRetryPolicy(RetryPolicy):
def __init__(self):
RetryPolicy.__init__(self, RetryOnRcCodeCondition(), ExponentialBackoffStrategy())