Closed bobwng closed 1 year ago
Got another listenKeyExpired event just now, it lasts less than 5 hours this time.
Can you provide a DEBUG log of ubwa please?
Here it is:
2022-06-01 12:10:50,659 [DEBUG ] 23539 140046298318592 protocol: % sending keepalive ping 2022-06-01 12:10:50,659 [DEBUG ] 23539 140046298318592 protocol: > PING 83 f7 ab a0 [binary, 4 bytes] 2022-06-01 12:10:50,698 [DEBUG ] 23539 140046298318592 protocol: < PONG 83 f7 ab a0 [binary, 4 bytes] 2022-06-01 12:10:50,698 [DEBUG ] 23539 140046298318592 protocol: % received keepalive pong 2022-06-01 12:10:50,788 [DEBUG ] 23539 140046298318592 protocol: < TEXT '{"stream":"ethusdt@miniTicker","data":{"e":"24h...","q":"5074685853.30"}}' [187 bytes] 2022-06-01 12:10:50,788 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:50,788 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_as_crash_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:50,789 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.set_heartbeat(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:51,046 [DEBUG ] 23539 140045981832960 protocol: % sending keepalive ping 2022-06-01 12:10:51,046 [DEBUG ] 23539 140045981832960 protocol: > PING 39 9b a4 cf [binary, 4 bytes] 2022-06-01 12:10:51,057 [DEBUG ] 23539 140046298318592 protocol: < TEXT '{"stream":"adausdt@miniTicker","data":{"e":"24h...q":"1998507369.69000"}}' [189 bytes] 2022-06-01 12:10:51,057 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:51,057 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_as_crash_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:51,058 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.set_heartbeat(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:51,077 [DEBUG ] 23539 140046334162688 protocol: < TEXT '{"stream":"bnbusdt@markPrice","data":{"e":"mark...00","T":1654070400000}}' [185 bytes] 2022-06-01 12:10:51,078 [DEBUG ] 23539 140046334162688 manager: BinanceWebSocketApiManager.is_stop_request(5714146bb496-39e3-6ee7-b81c-04b57f70) 2022-06-01 12:10:51,078 [DEBUG ] 23539 140046334162688 manager: BinanceWebSocketApiManager.is_stop_as_crash_request(5714146bb496-39e3-6ee7-b81c-04b57f70) 2022-06-01 12:10:51,078 [DEBUG ] 23539 140046334162688 manager: BinanceWebSocketApiManager.set_heartbeat(5714146bb496-39e3-6ee7-b81c-04b57f70) 2022-06-01 12:10:51,081 [DEBUG ] 23539 140045981832960 protocol: < PONG 39 9b a4 cf [binary, 4 bytes] 2022-06-01 12:10:51,081 [DEBUG ] 23539 140045981832960 protocol: % received keepalive pong 2022-06-01 12:10:51,122 [DEBUG ] 23539 140046298318592 protocol: < TEXT '{"stream":"solusdt@miniTicker","data":{"e":"24h...,"q":"904046299.7000"}}' [185 bytes] 2022-06-01 12:10:51,122 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:51,123 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_as_crash_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:51,123 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.set_heartbeat(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) REMOVE LINES... 2022-06-01 12:10:51,622 [DEBUG ] 23539 140046298318592 protocol: < TEXT '{"stream":"solusdt@miniTicker","data":{"e":"24h...,"q":"904049721.7300"}}' [185 bytes] 2022-06-01 12:10:51,622 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:51,622 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_as_crash_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:51,622 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.set_heartbeat(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:51,641 [DEBUG ] 23539 140045981832960 sockets: BinanceWebSocketApiSocket.start_socket(7b228620c70d-6023-b639-9040-3fd6dfa6, ['arr'], ['!userData'] - Received inner asyncio.TimeoutError 2022-06-01 12:10:51,641 [DEBUG ] 23539 140045981832960 manager: BinanceWebSocketApiManager.is_stop_request(7b228620c70d-6023-b639-9040-3fd6dfa6) 2022-06-01 12:10:51,641 [DEBUG ] 23539 140045981832960 manager: BinanceWebSocketApiManager.is_stop_as_crash_request(7b228620c70d-6023-b639-9040-3fd6dfa6) 2022-06-01 12:10:51,641 [DEBUG ] 23539 140045981832960 manager: BinanceWebSocketApiManager.set_heartbeat(7b228620c70d-6023-b639-9040-3fd6dfa6) REMOVE LINES... 2022-06-01 12:10:52,122 [DEBUG ] 23539 140046298318592 protocol: < TEXT '{"stream":"solusdt@miniTicker","data":{"e":"24h...,"q":"904051677.5300"}}' [185 bytes] 2022-06-01 12:10:52,122 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:52,122 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_as_crash_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:52,122 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.set_heartbeat(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:52,144 [DEBUG ] 23539 140045981832960 protocol: < TEXT '{"e": "listenKeyExpired", "E": 1654056652127}' [45 bytes] 2022-06-01 12:10:52,145 [DEBUG ] 23539 140045981832960 protocol: < TEXT '{"e": "listenKeyExpired", "E": 1654056652128}' [45 bytes] 2022-06-01 12:10:52,145 [DEBUG ] 23539 140045981832960 manager: BinanceWebSocketApiManager.is_stop_request(7b228620c70d-6023-b639-9040-3fd6dfa6) 2022-06-01 12:10:52,145 [DEBUG ] 23539 140045981832960 manager: BinanceWebSocketApiManager.is_stop_as_crash_request(7b228620c70d-6023-b639-9040-3fd6dfa6) 2022-06-01 12:10:52,145 [DEBUG ] 23539 140045981832960 manager: BinanceWebSocketApiManager.set_heartbeat(7b228620c70d-6023-b639-9040-3fd6dfa6) 2022-06-01 12:10:52,145 [DEBUG ] 23539 140045981832960 manager: BinanceWebSocketApiManager.is_stop_request(7b228620c70d-6023-b639-9040-3fd6dfa6) 2022-06-01 12:10:52,145 [DEBUG ] 23539 140045981832960 manager: BinanceWebSocketApiManager.is_stop_as_crash_request(7b228620c70d-6023-b639-9040-3fd6dfa6) 2022-06-01 12:10:52,146 [DEBUG ] 23539 140045981832960 manager: BinanceWebSocketApiManager.set_heartbeat(7b228620c70d-6023-b639-9040-3fd6dfa6) 2022-06-01 12:10:52,146 [INFO ] 23539 140046412805888 asyncio: Notifying 1 service(s) asynchronously. 2022-06-01 12:10:52,146 [DEBUG ] 23539 140046412805888 selector_events: Using selector: EpollSelector 2022-06-01 12:10:52,147 [DEBUG ] 23539 140045940647680 NotifyJSON: JSON POST URL:
2022-06-01 12:10:52,147 [DEBUG ] 23539 140045940647680 NotifyJSON: JSON Payload: {'version': '1.0', 'title': '', 'message': "Listen key expired: {'e': 'listenKeyExpired', 'E': 1654056652127}", 'type': 'info'} 2022-06-01 12:10:52,153 [DEBUG ] 23539 140046298318592 protocol: < TEXT '{"stream":"btcusdt@miniTicker","data":{"e":"24h...,"q":"11953661745.49"}}' [191 bytes] 2022-06-01 12:10:52,153 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:52,153 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.is_stop_as_crash_request(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca) 2022-06-01 12:10:52,153 [DEBUG ] 23539 140046298318592 manager: BinanceWebSocketApiManager.set_heartbeat(8ace05a5aa94-82ba-5b56-e41d-6a6fa0ca)
This time it lives over 10+ hours...
Please pay attention to the line with timestamp: 2022-06-01 12:10:51,641, it received inner asyncio.TimeoutError, and then got listenKeyExpired event at 2022-06-01 12:10:52,144.
Please let me know if need more information.
Checked the logs again, the "Received inner asyncio.TimeoutError" occurred not only right before listenKeyExpired event, it appears in lots of place even in several hours before got that event.
Recently I'm still frequently got listenKeyExpired event, and I changed the code to call create_stream() again after got that event. Meanwhile, it might send two listenKeyExpired events at almost same time, you should avoid to call create_stream() twice in that time.
Looks good in last whole week.
@oliver-zehentleitner Any ideas?
Hello Oliver, I am trying to replace Binance-Futures with your library and I am get quite a few ListenKeyExpired messages, how should I handle them ? Any suggestions ? Thanks in advance
Regards Andre
https://github.com/LUCIT-Systems-and-Development/unicorn-fy/issues/41 Exactly the same。。。
Hello Oliver, I am trying to replace Binance-Futures with your library and I am get quite a few ListenKeyExpired messages, how should I handle them ? Any suggestions ? Thanks in advance
Regards Andre
Just FYI, I added some code like below, it works well in last month, you can base it to get your own version:
elif event_type == "listenKeyExpired":
listen_key_expired_timestamp = datetime.fromtimestamp(stream_data['E'] / 1000)
self.logger.warning(f"Listen key expired at {listen_key_expired_timestamp}: {stream_data}")
if self.listen_key_expired_timestamp is None \
or listen_key_expired_timestamp - self.listen_key_expired_timestamp > timedelta(seconds=10):
# Never expired or last expired time is 10 seconds ago
self.listen_key_expired_timestamp = listen_key_expired_timestamp
self.bw_api_manager.create_stream(
["arr"], ["!userData"], api_key=self.config.BINANCE_API_KEY, api_secret=self.config.BINANCE_API_SECRET_KEY
)
else:
self.logger.warning(f"WARN: Not handled 'e' event: {stream_data}")
Hello Oliver, I am trying to replace Binance-Futures with your library and I am get quite a few ListenKeyExpired messages, how should I handle them ? Any suggestions ? Thanks in advance Regards Andre
Just FYI, I added some code like below, it works well in last month, you can base it to get your own version:
elif event_type == "listenKeyExpired": listen_key_expired_timestamp = datetime.fromtimestamp(stream_data['E'] / 1000) self.logger.warning(f"Listen key expired at {listen_key_expired_timestamp}: {stream_data}") if self.listen_key_expired_timestamp is None \ or listen_key_expired_timestamp - self.listen_key_expired_timestamp > timedelta(seconds=10): # Never expired or last expired time is 10 seconds ago self.listen_key_expired_timestamp = listen_key_expired_timestamp self.bw_api_manager.create_stream( ["arr"], ["!userData"], api_key=self.config.BINANCE_API_KEY, api_secret=self.config.BINANCE_API_SECRET_KEY ) else: self.logger.warning(f"WARN: Not handled 'e' event: {stream_data}")
@bobwng what will happen if, for example, an order is filled on the exchange before the creation, or at the time of the stream creation. the message is lost?
Hello Oliver, I am trying to replace Binance-Futures with your library and I am get quite a few ListenKeyExpired messages, how should I handle them ? Any suggestions ? Thanks in advance Regards Andre
Just FYI, I added some code like below, it works well in last month, you can base it to get your own version:
elif event_type == "listenKeyExpired": listen_key_expired_timestamp = datetime.fromtimestamp(stream_data['E'] / 1000) self.logger.warning(f"Listen key expired at {listen_key_expired_timestamp}: {stream_data}") if self.listen_key_expired_timestamp is None \ or listen_key_expired_timestamp - self.listen_key_expired_timestamp > timedelta(seconds=10): # Never expired or last expired time is 10 seconds ago self.listen_key_expired_timestamp = listen_key_expired_timestamp self.bw_api_manager.create_stream( ["arr"], ["!userData"], api_key=self.config.BINANCE_API_KEY, api_secret=self.config.BINANCE_API_SECRET_KEY ) else: self.logger.warning(f"WARN: Not handled 'e' event: {stream_data}")
@bobwng what will happen if, for example, an order is filled on the exchange before the creation, or at the time of the stream creation. the message is lost?
Hello diva,
in my experience the message is lost and all hell starts to break lose on your bots :( Cheers
Andre
Hello Oliver, I am trying to replace Binance-Futures with your library and I am get quite a few ListenKeyExpired messages, how should I handle them ? Any suggestions ? Thanks in advance Regards Andre
Just FYI, I added some code like below, it works well in last month, you can base it to get your own version:
elif event_type == "listenKeyExpired": listen_key_expired_timestamp = datetime.fromtimestamp(stream_data['E'] / 1000) self.logger.warning(f"Listen key expired at {listen_key_expired_timestamp}: {stream_data}") if self.listen_key_expired_timestamp is None \ or listen_key_expired_timestamp - self.listen_key_expired_timestamp > timedelta(seconds=10): # Never expired or last expired time is 10 seconds ago self.listen_key_expired_timestamp = listen_key_expired_timestamp self.bw_api_manager.create_stream( ["arr"], ["!userData"], api_key=self.config.BINANCE_API_KEY, api_secret=self.config.BINANCE_API_SECRET_KEY ) else: self.logger.warning(f"WARN: Not handled 'e' event: {stream_data}")
Hi Bob, thanks I will try your code, on the other hand I managed to keep away from those listenkeyexpired messages by getting the listenkey every 60 seconds ! Cheers Andre
Hello Oliver, I am trying to replace Binance-Futures with your library and I am get quite a few ListenKeyExpired messages, how should I handle them ? Any suggestions ? Thanks in advance Regards Andre
Just FYI, I added some code like below, it works well in last month, you can base it to get your own version:
elif event_type == "listenKeyExpired": listen_key_expired_timestamp = datetime.fromtimestamp(stream_data['E'] / 1000) self.logger.warning(f"Listen key expired at {listen_key_expired_timestamp}: {stream_data}") if self.listen_key_expired_timestamp is None \ or listen_key_expired_timestamp - self.listen_key_expired_timestamp > timedelta(seconds=10): # Never expired or last expired time is 10 seconds ago self.listen_key_expired_timestamp = listen_key_expired_timestamp self.bw_api_manager.create_stream( ["arr"], ["!userData"], api_key=self.config.BINANCE_API_KEY, api_secret=self.config.BINANCE_API_SECRET_KEY ) else: self.logger.warning(f"WARN: Not handled 'e' event: {stream_data}")
Hi Bob,
a question about your code:
If I had previously started a thread to wait for messages. If I use a replace_stream will I need to stop the old thread and start a new one ?
Thanks Andre
If I had previously started a thread to wait for messages. If I use a replace_stream will I need to stop the old thread and start a new one ?
I have no experience on replace_stream, per comments mentioned in the sample code below, looks like no need to stop the old stream manually:
thanks I will try your code, on the other hand I managed to keep away from those listenkeyexpired messages by getting the listenkey every 60 seconds !
That's great!
Just FYI that the lib should already have the keep alive related code, but not sure why it not works:
@bobwng @oliver-zehentleitner
self.restclient.keepalive_listen_key(stream_id)
def keepalive_listen_key(self,
stream_id=False,
api_key=False,
api_secret=False,
listen_key=False,
last_static_ping_listen_key=False):
with self.threading_lock:
self._init_vars(stream_id, api_key, api_secret, listen_key, last_static_ping_listen_key)
return self._do_request("keepalive")
def _do_request(self, action=False):
if action == "keepalive":
logger.info(f"BinanceWebSocketApiRestclient.keepalive_listen_key({str(self.listen_key_output)})")
method = "put"
try:
response = self._request(method, self.path_userdata, False, {'listenKey': str(self.listen_key)})
self.last_static_ping_listen_key = time.time()
return response
Very strange logic
@bobwng @oliver-zehentleitner
self.restclient.keepalive_listen_key(stream_id) def keepalive_listen_key(self, stream_id=False, api_key=False, api_secret=False, listen_key=False, last_static_ping_listen_key=False): with self.threading_lock: self._init_vars(stream_id, api_key, api_secret, listen_key, last_static_ping_listen_key) return self._do_request("keepalive") def _do_request(self, action=False): if action == "keepalive": logger.info(f"BinanceWebSocketApiRestclient.keepalive_listen_key({str(self.listen_key_output)})") method = "put" try: response = self._request(method, self.path_userdata, False, {'listenKey': str(self.listen_key)}) self.last_static_ping_listen_key = time.time() return response
Very strange logic
Yes, and I don't think it works, sometimes when I launch the bot, the first message it receives is a listenKeyExpired !!!
@oliver-zehentleitner @amdescombes @bobwng @dima-dmytruk23 I think I have fixed the this bug.
import logging
import time
import threading
import os
import json
from termcolor import colored, cprint
from unicorn_fy.unicorn_fy import UnicornFy
from unicorn_binance_websocket_api.manager import BinanceWebSocketApiManager
# create instances of BinanceWebSocketApiManager
#binance_websocket_api_manager = BinanceWebSocketApiManager(exchange="binance.com-futures", output_default="UnicornFy",throw_exception_if_unrepairable=True)
binance_websocket_api_manager = BinanceWebSocketApiManager(exchange="binance.com-futures", throw_exception_if_unrepairable=True)
# configure api key and secret for binance.com for Alice
apiKey = "apiKey"
secret = "secret"
# create the userData streams
alice_stream_id = binance_websocket_api_manager.create_stream('arr', '!userData', stream_label="Alice",stream_buffer_name=True,api_key=apiKey, api_secret=secret)
info_stream = binance_websocket_api_manager.get_stream_list()
print(alice_stream_id)
print('status',info_stream[alice_stream_id]['status'])
print('stop_request',info_stream[alice_stream_id]['stop_request'])#停止请求
print('crash_request',info_stream[alice_stream_id]['crash_request'])#崩溃请求
print('kill_request',info_stream[alice_stream_id]['kill_request'])#杀死请求
print('reconnects',info_stream[alice_stream_id]['reconnects'])#重连次数
# print(binance_websocket_api_manager.get_stream_statistic(alice_stream_id))
# 结果转成JSON
def str2json(result):
return UnicornFy.binance_com_futures_websocket(result)
def getdate2(t):
'''时间戳转换为时间'''
t1 = float(t)/1000
t2 = time.localtime(t1)
t3 = time.strftime("%Y-%m-%d %H:%M:%S", t2)
return t3
# # https://docs.python.org/3/library/logging.html#logging-levels
logging.basicConfig(level=logging.DEBUG,
filename=os.path.basename(__file__) + '.log',
format="{asctime} [{levelname:8}] {process} {thread} {module}: {message}",
style="{")
# Python线程退出条件有以下几种:
# 1、线程内的函数语句执行完毕,线程自动结束
# 2、线程内的函数抛出未处理的异常
def print_stream_buffer_data(binance_websocket_api_manager, stream_id):
side_aways ={
"BUYLONG":"买入开多",
"BUYSHORT":"买入平空",
"SELLSHORT":"卖出开空",
"SELLLONG":"卖出平多",
}
order_status = {
'NEWNEW':"挂单未成交",
'CANCELEDCANCELED':"撤单",
'TRADEFILLED':"挂单已成交",
'EXPIREDEXPIRED':"订单已过期",
'TRADEPARTIALLY_FILLED':'部分成交'
}
trad_types = {
"LIMIT":"限价单",
"TAKE_PROFIT":"止盈止损单",
"MARKET":"市价单"
}
while True:
try :
#有停止请求,则返回True ,否则返回 'False'。
if binance_websocket_api_manager.is_manager_stopping():
print("遇到错误了,正常运行程序并退出程序")
exit(0)
oldest_stream_data_from_stream_buffer = binance_websocket_api_manager.pop_stream_data_from_stream_buffer(stream_id)
if oldest_stream_data_from_stream_buffer is False:
time.sleep(0.01)
else:
oldest_stream_data_from_stream = json.loads(oldest_stream_data_from_stream_buffer)
print(oldest_stream_data_from_stream['e'])
if oldest_stream_data_from_stream['e'] == "listenKeyExpired":
binance_websocket_api_manager.kill_stream(stream_id)
binance_websocket_api_manager.set_restart_request(stream_id)
#binance_websocket_api_manager._restart_stream(stream_id)
else:
data = UnicornFy.binance_com_futures_websocket(oldest_stream_data_from_stream_buffer)
event_type = data["event_type"]
if event_type == "ORDER_TRADE_UPDATE":
#币种
symbol = data['symbol']
#方向
side = data['side']
#持仓方向
position_side = data['position_side']
#挂单价格
order_price = data['order_price']
#实际成交价格
order_avg_price = data['order_avg_price']
#挂单数量
order_quantity = data['order_quantity']
current_order_status = data['current_order_status']
current_execution_type = data['current_execution_type']
transaction_time = getdate2( data['transaction_time'])
last_executed_price = data['last_executed_price']
#交易编号 ex android_mJlmVJJhRdpoL2fnSAhB
client_order_id = data['client_order_id']
#交易ID ex 60952023909
order_id = data['order_id']
#这个目前没用
trade_id = data['trade_id']
#下单为 LIMIT 挂单止盈为TAKE_PROFIT
order_type = data['order_type']
trad_type = trad_types[order_type]
side_away = side_aways[side+position_side]
acction = order_status[current_execution_type + current_order_status]
cprint(f"订单状态:{acction} 信号状态:{event_type} 币种:{symbol} 下单动作:{side_away} 挂单价格:{order_price} 成交价格:{order_avg_price} 平仓价格:{last_executed_price} 挂单数量:{order_quantity} 时间:{transaction_time}",
'blue', 'on_white')
except BaseException as e :
print(e)
worker_thread = threading.Thread(target=print_stream_buffer_data, args=(binance_websocket_api_manager,alice_stream_id))
worker_thread.start()
@netsesame what will happen if, for example, an order is filled on the exchange before the creation, or at the time of the stream creation. the message is lost?
I see 2 solutions to the problem:
The first option is more reliable, in my opinion.
Hi, I'm fighting the same issue here with the user data stream stopping after listenKeyExpired
is received. In my case, I have two clients connected to the same Binance account and when one of them calls stop_stream()
(as part of its cleanup), the listen key gets deleted (there is a call to self.delete_listen_key_by_stream_id(stream_id)
inside stop_stream()
). If I understand the Binance docs correctly, there could only be a single listen key per account active at any given moment and its shared between all clients:
POST /fapi/v1/listenKey
Start a new user data stream. The stream will close after 60 minutes unless a keepalive is sent. If the account has an active listenKey, that listenKey will be returned and its validity will be extended for 60 minutes. [emphasis mine]
So, when the second client deletes the listen key before exiting, the first client will no longer receive messages on that listen key. Binance will not disconnect the websocket - it will simply stop sending data.
I tried calling replace_stream()
when listenKeyExpired
is received, but it does not solve the problem. For now, the only local remedy I see is to comment the delete call in the manager and let the key expire on its own if no other client is keeping it alive.
Thanks for the good reports and analysis.
stop_stream()
has from now on a new parameter called delete_listen_key
. So it is possible to disable the deletion on stop_stream()
.
replace_stream()
always calls stop_stream()
with delete_listen_key=False
from now on.
Thanks @hiliev
asyncio.TimeoutError
is not a fail, its just a timeout if we wait to long to receive a message we get an timeout, so we can break the eventloop and close streams which are receiving no data. Without that userData streams were not closeable without a received data through websocket.
I set the interval from refreshing the listen_key
to 10 min, before it was 30 which is equal to lifetime window.
If the problem persists, we can create a way to set the interval time manually. If necessary, the code for "keep alive" must be revised.
Version of this library.
unicorn_fy: 0.11.0 unicorn_binance_local_depth_cache: not found unicorn_binance_rest_api: not found unicorn_binance_trailing_stop_loss: not found unicorn_binance_websocket_api: 1.41.0
Solution to Issue cannot be found in the documentation or other Issues and also occurs in the latest version of this library.
Hardware?
VPS or other cloud hosting
Operating System?
Linux
Python version?
Python3.8
Installed packages
Logging output
Processing method?
process_stream_data
Used endpoint?
binance.com-coin_futures
Issue
I subscribe both !userData and !miniTicker stream, !userData stopped to get new update after got listenKeyExpired event. But last time(2022-05-30 00:42:24,114) both userData/miniTicker are stopped to send update.
There is no significant error/warning logs like "time out", "connection interrupted" etc. No related code change in recent days, except adding some new log specific for listenKeyExpired event. And the scripts never prompt such information in recent months.
I found API "PUT /fapi/v1/listenKey" not exposed, not sure if we can expose this API and then I can invoke it manually to prevent this event?