issork / gift

Godot IRC For Twitch addon
MIT License
150 stars 23 forks source link

TwitchAPI disconnects every 30 minutes #38

Open iRadEntertainment opened 8 months ago

iRadEntertainment commented 8 months ago

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

infohub-gather commented 8 months ago

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 7 months ago

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

infohub-gather commented 7 months ago

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 6 months ago

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