feat: emit with timeout

This feature allows to send a packet and expect an acknowledgement from
the server within the given delay.

Syntax:

```java
socket.emit("hello", "world", new AckWithTimeout(5000) {
    @Override
    public void onTimeout() {
        // ...
    }

    @Override
    public void onSuccess(Object... args) {
        // ...
    }
});
```

Related:

- https://github.com/socketio/socket.io-client-java/issues/309
- https://github.com/socketio/socket.io-client-java/pull/517
This commit is contained in:
Damien Arrachequesne
2022-07-08 19:46:05 +02:00
parent 73757635ed
commit fca3b9507d
3 changed files with 179 additions and 6 deletions

View File

@@ -0,0 +1,35 @@
package io.socket.client;
import java.util.Timer;
import java.util.TimerTask;
public abstract class AckWithTimeout implements Ack {
private final long timeout;
private final Timer timer = new Timer();
/**
*
* @param timeout delay in milliseconds
*/
public AckWithTimeout(long timeout) {
this.timeout = timeout;
}
@Override
public final void call(Object... args) {
this.timer.cancel();
this.onSuccess(args);
}
public final void schedule(TimerTask task) {
this.timer.schedule(task, this.timeout);
}
public final void cancelTimer() {
this.timer.cancel();
}
public abstract void onSuccess(Object... args);
public abstract void onTimeout();
}

View File

@@ -210,8 +210,32 @@ public class Socket extends Emitter {
Packet<JSONArray> packet = new Packet<>(Parser.EVENT, jsonArgs);
if (ack != null) {
logger.fine(String.format("emitting packet with ack id %d", ids));
Socket.this.acks.put(ids, ack);
final int ackId = Socket.this.ids;
logger.fine(String.format("emitting packet with ack id %d", ackId));
if (ack instanceof AckWithTimeout) {
final AckWithTimeout ackWithTimeout = (AckWithTimeout) ack;
ackWithTimeout.schedule(new TimerTask() {
@Override
public void run() {
// remove the ack from the map (to prevent an actual acknowledgement)
acks.remove(ackId);
// remove the packet from the buffer (if applicable)
Iterator<Packet<JSONArray>> iterator = sendBuffer.iterator();
while (iterator.hasNext()) {
if (iterator.next().id == ackId) {
iterator.remove();
}
}
ackWithTimeout.onTimeout();
}
});
}
Socket.this.acks.put(ackId, ack);
packet.id = ids++;
}
@@ -405,6 +429,12 @@ public class Socket extends Emitter {
this.subs = null;
}
for (Ack ack : acks.values()) {
if (ack instanceof AckWithTimeout) {
((AckWithTimeout) ack).cancelTimer();
}
}
this.io.destroy();
}