|
27 | 27 | import java.util.concurrent.ConcurrentMap; |
28 | 28 | import java.util.concurrent.ScheduledExecutorService; |
29 | 29 | import java.util.concurrent.TimeUnit; |
| 30 | +import java.util.concurrent.atomic.AtomicReference; |
30 | 31 |
|
31 | 32 | import org.apache.commons.logging.Log; |
32 | 33 | import org.apache.commons.logging.LogFactory; |
@@ -235,25 +236,40 @@ public void registerClient(String clientId, SseEmitter emitter) { |
235 | 236 | * first message |
236 | 237 | */ |
237 | 238 | public void registerClient(String clientId, SseEmitter emitter, boolean completeAfterMessage) { |
| 239 | + AtomicReference<SseEmitter> oldEmitter = new AtomicReference<>(); |
238 | 240 | this.clients.compute(clientId, (id, existing) -> { |
239 | 241 | if (existing == null) { |
240 | 242 | return new Client(id, emitter, completeAfterMessage); |
241 | 243 | } |
| 244 | + oldEmitter.set(existing.sseEmitter()); |
242 | 245 | existing.updateEmitter(emitter); |
| 246 | + existing.updateCompleteAfterMessage(completeAfterMessage); |
243 | 247 | return existing; |
244 | 248 | }); |
| 249 | + if (oldEmitter.get() != null) { |
| 250 | + try { |
| 251 | + oldEmitter.get().complete(); |
| 252 | + } |
| 253 | + catch (Exception e) { |
| 254 | + logger.debug("Error completing old emitter for client " + clientId, e); |
| 255 | + } |
| 256 | + } |
245 | 257 | } |
246 | 258 |
|
247 | 259 | /** |
248 | 260 | * Unregisters a client and unsubscribes the client from all events. |
249 | 261 | * @param clientId unique client identifier |
250 | 262 | */ |
251 | 263 | public void unregisterClient(String clientId) { |
252 | | - unsubscribeFromAllEvents(clientId); |
253 | | - Client removed = this.clients.remove(clientId); |
254 | | - if (removed != null) { |
| 264 | + AtomicReference<SseEmitter> removedEmitter = new AtomicReference<>(); |
| 265 | + this.clients.computeIfPresent(clientId, (id, client) -> { |
| 266 | + removedEmitter.set(client.sseEmitter()); |
| 267 | + unsubscribeFromAllEvents(id); |
| 268 | + return null; |
| 269 | + }); |
| 270 | + if (removedEmitter.get() != null) { |
255 | 271 | try { |
256 | | - removed.sseEmitter().complete(); |
| 272 | + removedEmitter.get().complete(); |
257 | 273 | } |
258 | 274 | catch (Exception e) { |
259 | 275 | logger.debug("Error completing emitter for client " + clientId, e); |
@@ -284,8 +300,8 @@ public void subscribe(String clientId, String event) { |
284 | 300 | * @param event the event name |
285 | 301 | */ |
286 | 302 | public void subscribeOnly(String clientId, String event) { |
287 | | - this.subscriptionRegistry.subscribe(clientId, event); |
288 | 303 | this.unsubscribeFromAllEvents(clientId, event); |
| 304 | + this.subscriptionRegistry.subscribe(clientId, event); |
289 | 305 | } |
290 | 306 |
|
291 | 307 | /** |
@@ -493,9 +509,30 @@ private void cleanUpClients() { |
493 | 509 | staleClients.add(entry.getKey()); |
494 | 510 | } |
495 | 511 | } |
496 | | - staleClients.forEach(this::unregisterClient); |
497 | | - if (!staleClients.isEmpty()) { |
498 | | - this.listener.afterClientsUnregistered(staleClients); |
| 512 | + Set<String> actuallyRemoved = new HashSet<>(); |
| 513 | + for (String clientId : staleClients) { |
| 514 | + long recheckExpiration = System.currentTimeMillis() - this.clientExpiration.toMillis(); |
| 515 | + AtomicReference<SseEmitter> removedEmitter = new AtomicReference<>(); |
| 516 | + this.clients.computeIfPresent(clientId, (id, client) -> { |
| 517 | + if (client.lastTransfer() < recheckExpiration) { |
| 518 | + removedEmitter.set(client.sseEmitter()); |
| 519 | + unsubscribeFromAllEvents(id); |
| 520 | + return null; |
| 521 | + } |
| 522 | + return client; |
| 523 | + }); |
| 524 | + if (removedEmitter.get() != null) { |
| 525 | + actuallyRemoved.add(clientId); |
| 526 | + try { |
| 527 | + removedEmitter.get().complete(); |
| 528 | + } |
| 529 | + catch (Exception e) { |
| 530 | + logger.debug("Error completing emitter for client " + clientId, e); |
| 531 | + } |
| 532 | + } |
| 533 | + } |
| 534 | + if (!actuallyRemoved.isEmpty()) { |
| 535 | + this.listener.afterClientsUnregistered(actuallyRemoved); |
499 | 536 | } |
500 | 537 | } |
501 | 538 | } |
|
0 commit comments