Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpClientConnection error after some Idle time when triggering a chatInputInteractionEventhandler that sends a response #1038

Closed
suizi opened this issue Nov 8, 2021 · 4 comments
Labels
has workaround Issue can be resolved through a workaround for now wontfix Maintainers have decided to not fix this issue

Comments

@suizi
Copy link

suizi commented Nov 8, 2021

Hello.

Context:
I'm currently working on simple discord4j bot that tracks the time we spend on our gaming server.
To display statistics I've created an application command and a respective ChatInputInteractionEvent listener to handle input and answer with some data packed into an embed.

To Reproduce:

GatewayDiscordClient gateway = DiscordClientBuilder.create(token).build().login().block();
gateway.getEventDispatcher().on(ChatInputInteractionEvent.class).doOnError(this::handleError).subscribe(this::handleCommand);
// where handleError does perform a print stacktrace and handleCommands sends an answer using event.reply(...)

Send a application command to message channel after some IDLE time.

Expected Behavior:
The server handles the message create event and is able to send a response.

Actual Behavior:
When the server was running in idle for about 15 minutes, triggering an message create event results in an exception on server side that the HTTP connection has been closed. When resending a message directly afterwards it works.
Is there a way to check if the connection is still available before processing the event's response, or activate some sort of self-fix?

The exact exception that occurrs is the following:

2021-11-08 12:35:09.674  WARN 5312 --- [ctor-http-nio-2] r.netty.http.client.HttpClientConnect    : [bb780ff9-10, L:/192.168.1.9:58908 - R:discord.com/162.159.135.232:443] The connection observed an error

java.io.IOException: An existing connection was forcibly closed by the remote host
	at java.base/sun.nio.ch.SocketDispatcher.read0(Native Method) ~[na:na]
	at java.base/sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43) ~[na:na]
	at java.base/sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:276) ~[na:na]
	at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:233) ~[na:na]
	at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:223) ~[na:na]
	at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:358) ~[na:na]
	at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:253) ~[netty-buffer-4.1.69.Final.jar:4.1.69.Final]
	at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132) ~[netty-buffer-4.1.69.Final.jar:4.1.69.Final]
	at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:350) ~[netty-transport-4.1.69.Final.jar:4.1.69.Final]
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151) ~[netty-transport-4.1.69.Final.jar:4.1.69.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.69.Final.jar:4.1.69.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.69.Final.jar:4.1.69.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.69.Final.jar:4.1.69.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.69.Final.jar:4.1.69.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-common-4.1.69.Final.jar:4.1.69.Final]
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.69.Final.jar:4.1.69.Final]
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.69.Final.jar:4.1.69.Final]
	at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

On client side the interaction looks like this:
image

I've experienced a similar problem when using MessageCreateEvent and text commands.

Version:
discord4j 3.2.0

Other:
I'm using discord4j version 3.2.0 and running in a v2.5.6 spring boot application using java 11.

Thanks in advance and sorry if this is just a "user"bug 👀. Please contact me if you need more information.
greetings suizi

@suizi suizi changed the title HttpClientConnect after some Idle time when triggering a chatInputInteractionEventhandler that sends a response HttpClientConnection error after some Idle time when triggering a chatInputInteractionEventhandler that sends a response Nov 8, 2021
@quanticc
Copy link
Member

quanticc commented Nov 8, 2021

Hi, even though Reactor Netty will attempt to check the connection health and even retry connection reset errors once, it can be possible that a network component (firewall, router, etc) is closing the connection due to inactivity.

You could experiment with customizing the connection pool maxIdleTime setting used by D4J like this:

DiscordClient.builder(token)
        .setReactorResources(ReactorResources.builder()
                .httpClient(ReactorResources.newHttpClient(ConnectionProvider.builder("custom")
                        .maxIdleTime(Duration.ofMinutes(10))
                        .build()))
                .build())
        .build()
        .login()
        .block();

Can also be done globally using a system property: https://projectreactor.io/docs/netty/snapshot/reference/index.html#_connection_pool

Please let us know if this helps

@suizi
Copy link
Author

suizi commented Nov 9, 2021

Hi thanks for the hint! I'll tweek the settings and check back on you in the next few days.

@twonirwana
Copy link

Hi, i had the same problem with problematic internet connection (bad IPv6 NAT). My solution was to always create a new connection lie this:

   DiscordClient discordClient = DiscordClientBuilder.create(token)
                .setReactorResources(ReactorResources.builder()
                        .httpClient(HttpClient.create()
                                .compress(true)
                                .keepAlive(false)
                                .followRedirect(true).secure())
                        .build()).build();

@NovaFox161 NovaFox161 added has workaround Issue can be resolved through a workaround for now wontfix Maintainers have decided to not fix this issue labels Jan 6, 2022
@quanticc
Copy link
Member

Retrying at the D4J client level can also work (context). For epoll:

DiscordClient client = DiscordClient.builder(token)
    .onClientResponse(
            ResponseFunction.retryWhen(
                RouteMatcher.any(),
                Retry.anyOf(Errors.NativeIoException.class)))
    .build();

For nio:

DiscordClient client = DiscordClient.builder(token)
    .onClientResponse(
            ResponseFunction.retryWhen(
                RouteMatcher.any(),
                Retry.anyOf(IOException.class)))
    .build();

after Retry.anyOf(...) the policy can be configured using methods like retryMax, backoff, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has workaround Issue can be resolved through a workaround for now wontfix Maintainers have decided to not fix this issue
Projects
None yet
Development

No branches or pull requests

4 participants