Compare commits

..

2 commits

Author SHA1 Message Date
9a646b9e8d discord-ws: Extract resume logic into own class
All checks were successful
ci/woodpecker/push/java Pipeline was successful
ci/woodpecker/push/oci-image-build Pipeline was successful
2024-12-04 20:03:08 +01:00
d41570bf55 discord-ws: Improve retry 2024-12-04 19:56:33 +01:00
3 changed files with 54 additions and 34 deletions

View file

@ -3,6 +3,7 @@ package de.hhhammer.dchat.discord.ws;
import de.hhhammer.dchat.discord.ws.connection.BackoffRetryer; import de.hhhammer.dchat.discord.ws.connection.BackoffRetryer;
import de.hhhammer.dchat.discord.ws.connection.ConnectionManager; import de.hhhammer.dchat.discord.ws.connection.ConnectionManager;
import de.hhhammer.dchat.discord.ws.connection.Connector; import de.hhhammer.dchat.discord.ws.connection.Connector;
import de.hhhammer.dchat.discord.ws.connection.ResumeConnector;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -32,7 +33,8 @@ public final class DiscordWebSocket {
public void start() throws InterruptedException { public void start() throws InterruptedException {
final var connector = new Connector(eventHandler); final var connector = new Connector(eventHandler);
final String initGatewayUrl = "wss://gateway.discord.gg/?v=10&encoding=json"; final String initGatewayUrl = "wss://gateway.discord.gg/?v=10&encoding=json";
final var connectionManager = new ConnectionManager(initGatewayUrl, discordApiKey, retryer); final ResumeConnector resumeConnector = new ResumeConnector(initGatewayUrl, discordApiKey);
final var connectionManager = new ConnectionManager(resumeConnector, retryer);
connectionManager.start(connector); connectionManager.start(connector);
} }
} }

View file

@ -10,49 +10,22 @@ import java.time.Duration;
public final class ConnectionManager { public final class ConnectionManager {
private static final Logger logger = LoggerFactory.getLogger(ConnectionManager.class); private static final Logger logger = LoggerFactory.getLogger(ConnectionManager.class);
private final String initGatewayUrl; private final ResumeConnector resumeConnector;
private final String token;
private final Retryer retryer; private final Retryer retryer;
public ConnectionManager(final String initGatewayUrl, final String token, final Retryer retryer) { public ConnectionManager(final ResumeConnector resumeConnector, final Retryer retryer) {
this.initGatewayUrl = initGatewayUrl; this.resumeConnector = resumeConnector;
this.token = token;
this.retryer = retryer; this.retryer = retryer;
} }
public void start(final Connector connector) throws InterruptedException { public void start(final Connector connector) throws InterruptedException {
while (retryer.hasRetriesLeft()) { while (retryer.hasRetriesLeft()) {
connect(connector);
final int reconnectDelayInSeconds = retryer.nextRetryInSeconds(); final int reconnectDelayInSeconds = retryer.nextRetryInSeconds();
Thread.sleep(Duration.ofSeconds(reconnectDelayInSeconds)); Thread.sleep(Duration.ofSeconds(reconnectDelayInSeconds));
resumeConnector.connect(connector);
logger.info("Reconnecting");
} }
logger.info("No retries left");
} }
private void connect(final Connector connector) {
ConnectionConfig mutConnectionConfig = new ConnectionConfig(initGatewayUrl, new IdendificationConnectionInitiator(token));
boolean isResumable = true;
while (isResumable) {
final CloseEvent closeEvent = connector.connect(mutConnectionConfig);
isResumable = switch (closeEvent) {
case CloseEvent.ResumableCloseEvent resumableCloseEvent -> {
if (resumableCloseEvent.resumeGatewayUrl() == null) {
logger.warn("Unable to resume: Missing resume URL");
yield false;
}
mutConnectionConfig = new ConnectionConfig(
resumableCloseEvent.resumeGatewayUrl(),
new ResumeConnectionInitiator(
token,
resumableCloseEvent.sessionId(),
resumableCloseEvent.lastSequence()
)
);
yield true;
}
case CloseEvent.UnresumableCloseEvent unresumableCloseEvent -> false;
case CloseEvent.UnrecoverableCloseEvent unrecoverableCloseEvent ->
throw new IllegalStateException("Unable to establish connection to the Discord gateway");
};
}
}
} }

View file

@ -0,0 +1,45 @@
package de.hhhammer.dchat.discord.ws.connection;
import de.hhhammer.dchat.discord.ws.connection.event.CloseEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class ResumeConnector {
private static Logger logger = LoggerFactory.getLogger(ResumeConnector.class);
private final String initGatewayUrl;
private final String token;
public ResumeConnector(final String initGatewayUrl, final String token) {
this.initGatewayUrl = initGatewayUrl;
this.token = token;
}
public void connect(final Connector connector) {
ConnectionConfig mutConnectionConfig = new ConnectionConfig(initGatewayUrl, new IdendificationConnectionInitiator(token));
boolean isResumable = true;
while (isResumable) {
final CloseEvent closeEvent = connector.connect(mutConnectionConfig);
isResumable = switch (closeEvent) {
case CloseEvent.ResumableCloseEvent resumableCloseEvent -> {
if (resumableCloseEvent.resumeGatewayUrl() == null) {
logger.warn("Unable to resume: Missing resume URL");
yield false;
}
mutConnectionConfig = new ConnectionConfig(
resumableCloseEvent.resumeGatewayUrl(),
new ResumeConnectionInitiator(
token,
resumableCloseEvent.sessionId(),
resumableCloseEvent.lastSequence()
)
);
logger.info("Resuming connection");
yield true;
}
case CloseEvent.UnresumableCloseEvent unresumableCloseEvent -> false;
case CloseEvent.UnrecoverableCloseEvent unrecoverableCloseEvent ->
throw new IllegalStateException("Unable to establish connection to the Discord gateway");
};
}
}
}