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

Implement JDA#restart #1459

Open
wants to merge 2 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/main/java/net/dv8tion/jda/api/JDA.java
Original file line number Diff line number Diff line change
Expand Up @@ -1878,6 +1878,23 @@ default List<Emote> getEmotesByName(@Nonnull String name, boolean ignoreCase)
*/
void shutdownNow();

/**
* Restarts this JDA session.
* <br>This will not restart the process, you cannot use this to update the your code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* <br>This will not restart the process, you cannot use this to update the your code.
* <br>This will not restart the process, you cannot use this to update your code.

*
* <p>This method is a last measure to fix a broken session. It will do the following:
* <ol>
* <li>Stop listening to events except for {@link net.dv8tion.jda.api.events.LifecycleEvent LifecycleEvents}</li>
MinnDevelopment marked this conversation as resolved.
Show resolved Hide resolved
* <li>Stop all currently queued requests with {@link #cancelRequests()}</li>
* <li>Invalidate and restart the gateway connection</li>
* </ol>
* It is not recommended to do this under normal operation, or in any regular intervals. This is truly supposed to be a panic button.
*
* @throws IllegalStateException
* If this JDA session was shutdown. You cannot recover after shutting down!
*/
void restart();

///**
// * Installs an auxiliary cable into the given port of your system.
// *
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
* <p>When reconnecting was successful either a {@link net.dv8tion.jda.api.events.ReconnectedEvent ReconnectEvent}
* <b>or</b> {@link net.dv8tion.jda.api.events.ResumedEvent ResumedEvent} is fired.
*/
public class DisconnectEvent extends Event
public class DisconnectEvent extends Event implements LifecycleEvent
{
protected final WebSocketFrame serverCloseFrame;
protected final WebSocketFrame clientCloseFrame;
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/net/dv8tion/jda/api/events/LifecycleEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2015-2020 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.dv8tion.jda.api.events;

/**
* Marker interface for all events that are strictly related to the lifecycle of a JDA session.
*
* @see net.dv8tion.jda.api.JDA#restart() restart()
*/
public interface LifecycleEvent extends GenericEvent
{
}
2 changes: 1 addition & 1 deletion src/main/java/net/dv8tion/jda/api/events/ReadyEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* <p>Can be used to indicate when JDA finished populating internal objects and is ready to be used.
* When this is fired all <b>available</b> entities are cached and accessible.
*/
public class ReadyEvent extends Event
public class ReadyEvent extends Event implements LifecycleEvent
{
private final int availableGuilds;
private final int unavailableGuilds;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
* <p>Can be used to mark the continuation of event flow which was stopped by the {@link net.dv8tion.jda.api.events.DisconnectEvent DisconnectEvent}.
* User should replace any cached Objects (like User/Guild objects).
*/
public class ReconnectedEvent extends Event
public class ReconnectedEvent extends Event implements LifecycleEvent
{
public ReconnectedEvent(@Nonnull JDA api, long responseNumber)
{
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/net/dv8tion/jda/api/events/ResumedEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
*
* <p>Can be used to marks the continuation of event flow stopped by the {@link net.dv8tion.jda.api.events.DisconnectEvent DisconnectEvent}.
*/
public class ResumedEvent extends Event
public class ResumedEvent extends Event implements LifecycleEvent
{
public ResumedEvent(@Nonnull JDA api, long responseNumber)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
* Indicates that JDA has fully disconnected from Discord and will not attempt to reconnect again.
* <br>At this stage all internal cache is invalid!
*/
public class ShutdownEvent extends Event
public class ShutdownEvent extends Event implements LifecycleEvent
{
protected final OffsetDateTime shutdownTime;
protected final int code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
*
* <p>Identifier: {@code status}
*/
public class StatusChangeEvent extends Event implements UpdateEvent<JDA, JDA.Status>
public class StatusChangeEvent extends Event implements UpdateEvent<JDA, JDA.Status>, LifecycleEvent
{
public static final String IDENTIFIER = "status";

Expand Down
10 changes: 10 additions & 0 deletions src/main/java/net/dv8tion/jda/internal/JDAImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,16 @@ private void closeAudioConnections()
.forEach(m -> m.closeAudioConnection(ConnectionStatus.SHUTTING_DOWN));
}

@Override
public void restart()
{
if (status == Status.SHUTDOWN || status == Status.SHUTTING_DOWN)
throw new IllegalStateException("Cannot restart a JDA session after shutdown!");
eventManager.prepareRestart(); // stop handling events
cancelRequests(); // stop executing any pending requests
getClient().close(1000, WebSocketClient.INVALIDATE_REASON); // drop session and start over
}

@Override
public long getResponseTotal()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package net.dv8tion.jda.internal.hooks;

import net.dv8tion.jda.api.events.GenericEvent;
import net.dv8tion.jda.api.events.LifecycleEvent;
import net.dv8tion.jda.api.events.ReconnectedEvent;
import net.dv8tion.jda.api.hooks.IEventManager;
import net.dv8tion.jda.api.hooks.InterfacedEventManager;
import net.dv8tion.jda.internal.JDAImpl;
Expand All @@ -30,13 +32,19 @@ public class EventManagerProxy implements IEventManager
{
private final ExecutorService executor;
private IEventManager subject;
private boolean awaitRestart = false;

public EventManagerProxy(IEventManager subject, ExecutorService executor)
{
this.subject = subject;
this.executor = executor;
}

public void prepareRestart()
{
awaitRestart = true; // stop handling events until shutdown
}

public void setSubject(IEventManager subject)
{
this.subject = subject == null ? new InterfacedEventManager() : subject;
Expand All @@ -62,6 +70,14 @@ public void unregister(@Nonnull Object listener)
@Override
public void handle(@Nonnull GenericEvent event)
{
if (awaitRestart)
{
if (event instanceof ReconnectedEvent)
awaitRestart = false;
else if (!(event instanceof LifecycleEvent))
return; // we are currently restarting, discard non-lifecycle events
}

try
{
if (executor != null && !executor.isShutdown())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public class WebSocketClient extends WebSocketAdapter implements WebSocketListen
public static final int IDENTIFY_DELAY = 5;
public static final int ZLIB_SUFFIX = 0x0000FFFF;

protected static final String INVALIDATE_REASON = "INVALIDATE_SESSION";
public static final String INVALIDATE_REASON = "INVALIDATE_SESSION";
protected static final long IDENTIFY_BACKOFF = TimeUnit.SECONDS.toMillis(SessionController.IDENTIFY_DELAY); // same as 1000 * IDENTIFY_DELAY

protected final JDAImpl api;
Expand Down