Skip to content
This repository has been archived by the owner on Jul 10, 2024. It is now read-only.

Commit

Permalink
Improved the RestAction Implementation
Browse files Browse the repository at this point in the history
- Added RequestHandler#processQueue and RequestHandler#queueRequest
- Modified RestAction#queue
- Added the usage of caching back to RJA#retrieve...
- Added some extra Null-Checks
  • Loading branch information
JoshiCodes committed Jun 11, 2023
1 parent be828e8 commit f3866d5
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 57 deletions.
40 changes: 33 additions & 7 deletions src/main/java/de/joshicodes/rja/RJA.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,11 @@ public void shutdownNow() {
*
*/
public RestAction<User> retrieveUser(String id) {
return new RestAction<>(this, () -> new FetchUserRequest(id));
final RJA rja = this;
return new SimpleRestAction<>(this, () -> {
if(userCache.containsKey(id)) return userCache.get(id);
else return new RestAction<>(rja, () -> new FetchUserRequest(id)).complete();
});
}

public RestAction<Member> retrieveMember(final Server server, final User user) {
Expand All @@ -186,15 +190,30 @@ public RestAction<Message> retrieveMessage(String channel, String id) {
}

public RestAction<Message> retrieveMessage(String channel, String id, boolean forceFetch) {
return new RestAction<>(this, () -> new FetchMessageRequest(channel, id));
if(channel == null || channel.isEmpty() || id == null || id.isEmpty()) {
throw new IllegalArgumentException("Channel and ID cannot be null or empty");
}
final RJA rja = this;
return new SimpleRestAction<>(this, () -> {
if(messageCache.containsKey(id) && !forceFetch) return messageCache.get(id);
else return new RestAction<>(rja, () -> new FetchMessageRequest(channel, id)).complete();
});
}

public RestAction<Emoji> retrieveEmoji(String id) {
return new RestAction<>(this, () -> new FetchEmojiRequest(id));
final RJA rja = this;
return new SimpleRestAction<>(this, () -> {
if(emojiCache.containsKey(id)) return emojiCache.get(id);
else return new RestAction<>(rja, () -> new FetchEmojiRequest(id)).complete();
});
}

public RestAction<DirectChannel> retrieveDirectChannel(String id) {
return new RestAction<>(this, () -> new OpenDirectMessageRequest(id));
final RJA rja = this;
return new SimpleRestAction<>(this, () -> {
if(channelCache.containsKey(id) && channelCache.get(id) instanceof DirectChannel direct) return direct;
else return new RestAction<>(rja, () -> new OpenDirectMessageRequest(id)).complete();
});
}

/**
Expand All @@ -204,18 +223,25 @@ public RestAction<DirectChannel> retrieveDirectChannel(String id) {
* @return The RestAction containing the channel. Use {@link RestAction#complete()} or {@link RestAction#queue} to get the channel. Channel can be null.
*/
public RestAction<GenericChannel> retrieveChannel(String id) {
return new RestAction<GenericChannel>(this, () -> new FetchChannelRequest(id));
final RJA rja = this;
return new SimpleRestAction<>(this, () -> {
if(channelCache.containsKey(id)) return channelCache.get(id);
else return new RestAction<>(rja, () -> new FetchChannelRequest(id)).complete();
});
}

public TextChannel retrieveTextChannel(String id) {
public TextChannel getTextChannel(String id) {
GenericChannel c = retrieveChannel(id).complete();
if(c instanceof TextChannel tc) return tc;
else throw new InvalidChannelTypeException(id, ChannelType.TEXT_CHANNEL, c.getType());
}

public RestAction<Server> retrieveServer(String serverId) {
final RJA rja = this;
return new RestAction<>(this, () -> new FetchServerRequest(serverId));
return new SimpleRestAction<>(this, () -> {
if(serverCache.containsKey(serverId)) return serverCache.get(serverId);
else return new RestAction<>(rja, () -> new FetchServerRequest(serverId)).complete();
});
}

public void cacheMessage(Message message) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@ public IncomingEvent handle(RJA rja, JsonObject object) {
Message message;
if(!inCache) {
// Message not in cache, cannot update with partial data -> fetch full message
RestResponse<Message> response = rja.getRequestHandler().fetchRequest(rja, new FetchMessageRequest(channel, id));
if(response.isOk()) {
message = response.object();
if(channel != null && id != null) {
RestResponse<Message> response = rja.getRequestHandler().fetchRequest(rja, new FetchMessageRequest(channel, id));
if(response.isOk()) {
message = response.object();
} else return null;
} else return null;
} else message = rja.getMessageCache().getIf(m -> m.equals(id));
Message updated = Message.from(rja, object.get("data").getAsJsonObject(), message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ public RestAction<MessageReaction> react(String emoji) {
AddReactionRequest request = new AddReactionRequest(getChannelId(), getId(), emoji);
getRJA().getRequestHandler().fetchRequest(getRJA(), request);
MessageReaction reaction = getReaction(emoji);
if(reaction == null) return null;
reaction.addReaction(getRJA().retrieveSelfUser().complete().getId());
return reaction;
});
Expand Down
39 changes: 38 additions & 1 deletion src/main/java/de/joshicodes/rja/requests/RequestHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import de.joshicodes.rja.requests.packet.PingRequest;
import de.joshicodes.rja.requests.rest.RestRequest;
import de.joshicodes.rja.requests.rest.RestResponse;
import de.joshicodes.rja.rest.RestAction;
import de.joshicodes.rja.util.Pair;
import org.java_websocket.exceptions.WebsocketNotConnectedException;
import org.java_websocket.framing.CloseFrame;
Expand All @@ -22,6 +23,7 @@
import java.net.URISyntaxException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

public class RequestHandler {

Expand All @@ -33,10 +35,14 @@ public class RequestHandler {
private final List<EventListener> listeners;
private final List<IncomingEvent> events;

private final HashMap<RestAction<?>, Pair<Consumer<Object>, Consumer<Throwable>>> actionQueue;
private boolean processingQueue = false;

public RequestHandler(RJABuilder rja, List<EventListener> listeners, List<IncomingEvent> events) throws URISyntaxException {
this.rja = rja;
this.listeners = listeners;
this.events = events;
this.actionQueue = new HashMap<>();
rja.getLogger().info("Connecting...");
this.socket = new RequestSocket(this);
}
Expand Down Expand Up @@ -68,7 +74,7 @@ public void run() {
*
* @deprecated Use {@link #fetchRequest(RJA, RestRequest)} instead
*/
@Deprecated(forRemoval = true)
@Deprecated(forRemoval = true, since = "1.1-alpha.1")
public <T> T sendRequest(final RJA rja, RestRequest<T> request) {
final RJABuilder builder = this.rja;
Pair<Integer, JsonElement> multi = builder.makeRequest(request);
Expand All @@ -80,6 +86,37 @@ public <T> T sendRequest(final RJA rja, RestRequest<T> request) {
return request.fetch(rja, multi.getFirst(), e);
}

private void processQueue() {
if(processingQueue || actionQueue.isEmpty())
return;
processingQueue = true;
new Thread(() -> {
Iterator<RestAction<?>> iterator = actionQueue.keySet().iterator();
while(iterator.hasNext()) {
final RestAction<?> action = iterator.next();
final Pair<Consumer<Object>, Consumer<Throwable>> pair = actionQueue.get(action);
try {
Object result = action.complete();
if(pair.getFirst() != null) {
pair.getFirst().accept(result);
}
} catch (Exception e) {
e.printStackTrace();
if(pair.getSecond() != null) {
pair.getSecond().accept(e);
}
}
iterator.remove();
}
processingQueue = false;
}).start();
}

public void queueRequest(RestAction<?> action, Consumer<Object> success, Consumer<Throwable> failure) {
actionQueue.put(action, new Pair<>(success, failure));
processQueue();
}

public <T> RestResponse<T> fetchRequest(final RJA rja, RestRequest<T> request) {
final RJABuilder builder = this.rja;
Pair<Integer, JsonElement> multi = builder.makeRequest(request);
Expand Down
55 changes: 9 additions & 46 deletions src/main/java/de/joshicodes/rja/rest/RestAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
import de.joshicodes.rja.requests.rest.RestResponse;
import de.joshicodes.rja.util.Pair;

import javax.annotation.Nullable;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class RestAction<R> {
Expand All @@ -36,7 +34,7 @@ protected Pair<Long, R> execute() throws Exception {
public R complete() {
int attempts = 0;
long retryAfter = 0;
while (attempts < MAX_ATTEMPTS) {
while (retryAfter != -1 && attempts < MAX_ATTEMPTS) {
try {
Pair<Long, R> result = execute();
if(result == null) {
Expand All @@ -48,18 +46,18 @@ public R complete() {
// Successfully got a result, call the success consumer and return
return result.getSecond();
}
// Got ratelimited, wait and try again
try {
Thread.sleep(retryAfter);
} catch (InterruptedException e) {
e.printStackTrace();
}
attempts++;
} catch (Exception e) {
// Failed to get a result
e.printStackTrace();
continue;
}
// Got ratelimited, wait and try again
try {
Thread.sleep(retryAfter);
} catch (InterruptedException e) {
e.printStackTrace();
}
attempts++;
}
throw new RatelimitException(this, request.get());
}
Expand All @@ -73,42 +71,7 @@ public void queue(Consumer<R> success) {
}

public void queue(Consumer<R> success, Consumer<Throwable> failure) {
final RestAction<R> action = this;
new Thread(() -> {
int attempts = 0;
long retryAfter = 0;
while (attempts < MAX_ATTEMPTS) {
try {
Pair<Long, R> result = execute();
if(result == null) {
// Failed to get a result, throw an exception
throw new RatelimitException(action, request.get());
}
retryAfter = result.getFirst();
if(retryAfter == -1) {
// Successfully got a result, call the success consumer and return
if(success != null) {
success.accept(result.getSecond());
}
return;
}
// Got ratelimited, wait and try again
try {
Thread.sleep(retryAfter + 100); // Add 100ms to the ratelimit to make sure it's over
} catch (InterruptedException e) {
e.printStackTrace();
}
attempts++;
} catch (Exception e) {
// Failed to get a result
e.printStackTrace();
continue;
}
}
if(failure != null) {
failure.accept(new RatelimitException(action, request.get()));
}
}).start();
rja.getRequestHandler().queueRequest(this, (Consumer<Object>) success, failure);
}

public RJA getRJA() {
Expand Down

0 comments on commit f3866d5

Please sign in to comment.