TwitchAPI disconnects every 30 minutes #38

Open
opened 2024-01-01 19:32:04 +01:00 by iRadEntertainment · 4 comments
iRadEntertainment commented 2024-01-01 19:32:04 +01:00 (Migrated from github.com)

So apparently the client connection cannot stay open forever and it disconnects after some time.

So apparently the client connection cannot stay open forever and it disconnects after some time.
infohub-gather commented 2024-01-07 16:18:28 +01:00 (Migrated from github.com)

Same issue, but I still need to update gift to the latest build,but it does seem to disconnect (since December) . If I got any valuable debug information I will add it here.

Same issue, but I still need to update gift to the latest build,but it does seem to disconnect (since December) . If I got any valuable debug information I will add it here.
iRadEntertainment commented 2024-01-14 12:51:41 +01:00 (Migrated from github.com)

This issue should be renamed: I dug a little more into HTTPClient class to figure out what was wrong.
I was getting the error:
request: Condition "status != STATUS_CONNECTED" is true. Returned: ERR_INVALID_PARAMETER
when using requests from the TwitchAPIConnection.

I believe the problem was related to having a request call while client.get_status() == HTTPClient.STATUS_BODY.

My hacky and NOT IDEAL solution has been to wait to finish polling the body within the request function.

Original code in TwitchAPIConnection:

func poll() -> void:
	client.poll()
	if (client.get_status() == HTTPClient.STATUS_BODY):
		client_response += client.read_response_body_chunk()
	elif (!client_response.is_empty()):
		received_response.emit(client_response.get_string_from_utf8())
		client_response.clear()


func request(method : int, url : String, headers : PackedStringArray, body : String = "") -> Dictionary:
	client.request(method, url, headers, body)
	var response = await(received_response)
	match (client.get_response_code()):
		401:
			id_conn.token_invalid.emit()
			return {}
	return JSON.parse_string(response)

My edits to code in TwitchAPIConnection:

func poll() -> void:
	client.poll()
	if (client.get_status() == HTTPClient.STATUS_BODY):
		client_response += client.read_response_body_chunk()
	elif (!client_response.is_empty()):
		received_response.emit(client_response.get_string_from_utf8())
		client_response.clear()


func request(method : int, url : String, headers : PackedStringArray, body : String = "") -> Dictionary:
	# --- MY HACKED SOLUTION
	while client.get_status() != HTTPClient.STATUS_CONNECTED:
		while client.get_status() == HTTPClient.STATUS_CONNECTING:
			await get_tree().create_timer(0.1).timeout
		if client.get_status() in [HTTPClient.STATUS_DISCONNECTED, HTTPClient.STATUS_CONNECTION_ERROR]:
			client.connect_to_host("https://api.twitch.tv", -1, TLSOptions.client())
		else:
			client.poll()
			if client.get_status() == HTTPClient.STATUS_BODY:
				client_response += client.read_response_body_chunk()
			elif (!client_response.is_empty()):
				received_response.emit(client_response.get_string_from_utf8())
	# --- MY HACKED SOLUTION
	client.request(method, url, headers, body)
	var response = await(received_response)
	match (client.get_response_code()):
		401:
			id_conn.token_invalid.emit()
			return {}
	return JSON.parse_string(response)

I am not confident in my network connection knowledge, so I won't suggest this as a definitive solution. But I hope this can help somehow.
If I have any updates or more errors related to connectivity I'll post them here.
Btw thank you issork for your amazing work!

EDIT: In the original response I used OS.delay_msec(50) which is a blocking thread solution. Not ideal. So I changed it to await get_tree().create_timer(0.1).timeout

This issue should be renamed: I dug a little more into HTTPClient class to figure out what was wrong. I was getting the error: `request: Condition "status != STATUS_CONNECTED" is true. Returned: ERR_INVALID_PARAMETER` when using requests from the `TwitchAPIConnection`. I believe the problem was related to having a request call while `client.get_status() == HTTPClient.STATUS_BODY`. My hacky and NOT IDEAL solution has been to wait to finish polling the body within the `request` function. Original code in `TwitchAPIConnection`: ```GDScript func poll() -> void: client.poll() if (client.get_status() == HTTPClient.STATUS_BODY): client_response += client.read_response_body_chunk() elif (!client_response.is_empty()): received_response.emit(client_response.get_string_from_utf8()) client_response.clear() func request(method : int, url : String, headers : PackedStringArray, body : String = "") -> Dictionary: client.request(method, url, headers, body) var response = await(received_response) match (client.get_response_code()): 401: id_conn.token_invalid.emit() return {} return JSON.parse_string(response) ``` My edits to code in `TwitchAPIConnection`: ```GDScript func poll() -> void: client.poll() if (client.get_status() == HTTPClient.STATUS_BODY): client_response += client.read_response_body_chunk() elif (!client_response.is_empty()): received_response.emit(client_response.get_string_from_utf8()) client_response.clear() func request(method : int, url : String, headers : PackedStringArray, body : String = "") -> Dictionary: # --- MY HACKED SOLUTION while client.get_status() != HTTPClient.STATUS_CONNECTED: while client.get_status() == HTTPClient.STATUS_CONNECTING: await get_tree().create_timer(0.1).timeout if client.get_status() in [HTTPClient.STATUS_DISCONNECTED, HTTPClient.STATUS_CONNECTION_ERROR]: client.connect_to_host("https://api.twitch.tv", -1, TLSOptions.client()) else: client.poll() if client.get_status() == HTTPClient.STATUS_BODY: client_response += client.read_response_body_chunk() elif (!client_response.is_empty()): received_response.emit(client_response.get_string_from_utf8()) # --- MY HACKED SOLUTION client.request(method, url, headers, body) var response = await(received_response) match (client.get_response_code()): 401: id_conn.token_invalid.emit() return {} return JSON.parse_string(response) ``` I am not confident in my network connection knowledge, so I won't suggest this as a definitive solution. But I hope this can help somehow. If I have any updates or more errors related to connectivity I'll post them here. Btw thank you issork for your amazing work! EDIT: In the original response I used `OS.delay_msec(50)` which is a blocking thread solution. Not ideal. So I changed it to `await get_tree().create_timer(0.1).timeout`
infohub-gather commented 2024-01-30 10:50:07 +01:00 (Migrated from github.com)

Nice work @iRadEntertainment !

I get this as my output currently in debug mode (as spam) :
At: res://addons/gift/gift_node.gd:292:_process() Connecting to Twitch IRC. Reconnecting to Twitch...

So it probably is indeed to do with re-establishing of the connection. Also I have been tinkering with other APIs and the reconnection problem is also found in a few other APIs, if I read their message boards. So perhaps something has changed since last year that breaks some connection codes.

This week I should be able to test a few setups as well, if I can add any fresh findings to this discussion I will. My speciality is not really in networking so lets see how it goes.

Nice work @iRadEntertainment ! I get this as my output currently in debug mode (as spam) : `At: res://addons/gift/gift_node.gd:292:_process() Connecting to Twitch IRC. Reconnecting to Twitch...` So it probably is indeed to do with re-establishing of the connection. Also I have been tinkering with other APIs and the reconnection problem is also found in a few other APIs, if I read their message boards. So perhaps something has changed since last year that breaks some connection codes. This week I should be able to test a few setups as well, if I can add any fresh findings to this discussion I will. My speciality is not really in networking so lets see how it goes.
ZeikJT commented 2024-02-17 21:54:09 +01:00 (Migrated from github.com)

Can't seem to use the updated get_tree() code because the current TwitchAPIConnection extends RefCounted which is not a Node. Had to go back to using the blocking sleep, feels bad, but works?

EDIT: I still get eventual disconnects and status -1

Can't seem to use the updated `get_tree()` code because the current TwitchAPIConnection extends RefCounted which is not a Node. Had to go back to using the blocking sleep, feels bad, but works? EDIT: I still get eventual disconnects and status -1
Sign in to join this conversation.
No description provided.