|
11 | 11 | import net.swofty.data.DataReader; |
12 | 12 | import net.swofty.data.DataWriter; |
13 | 13 | import net.swofty.data.format.JsonFormat; |
14 | | -import redis.clients.jedis.Jedis; |
15 | | -import redis.clients.jedis.JedisPool; |
16 | | -import redis.clients.jedis.JedisPubSub; |
17 | 14 |
|
18 | 15 | import java.lang.reflect.Type; |
19 | | -import java.nio.charset.StandardCharsets; |
20 | 16 | import java.util.*; |
21 | 17 | import java.util.concurrent.ConcurrentHashMap; |
22 | 18 |
|
23 | 19 | public class DistributedEventBus extends EventBus { |
24 | 20 | private static final Gson GSON = new GsonBuilder().create(); |
25 | 21 | private static final Type MAP_TYPE = new TypeToken<Map<String, Object>>() {}.getType(); |
26 | 22 |
|
27 | | - private final JedisPool pool; |
28 | | - private final String channel; |
| 23 | + private final PubSubHandler pubSubHandler; |
29 | 24 | private final String nodeId; |
30 | 25 | private final JsonFormat serializationFormat = new JsonFormat(); |
31 | 26 |
|
32 | 27 | private final ConcurrentHashMap<String, DataField<?>> fieldRegistry = new ConcurrentHashMap<>(); |
33 | 28 | private final ConcurrentHashMap<String, LinkType<?>> linkTypeRegistry = new ConcurrentHashMap<>(); |
34 | 29 |
|
35 | | - private Thread subscriberThread; |
36 | | - private volatile JedisPubSub activeSub; |
37 | | - private volatile boolean running = true; |
38 | | - |
39 | | - public DistributedEventBus(JedisPool pool) { |
40 | | - this(pool, "swofty:events", UUID.randomUUID().toString()); |
| 30 | + public DistributedEventBus(PubSubHandler pubSubHandler) { |
| 31 | + this(pubSubHandler, UUID.randomUUID().toString()); |
41 | 32 | } |
42 | 33 |
|
43 | | - public DistributedEventBus(JedisPool pool, String channel, String nodeId) { |
44 | | - this.pool = pool; |
45 | | - this.channel = channel; |
| 34 | + public DistributedEventBus(PubSubHandler pubSubHandler, String nodeId) { |
| 35 | + this.pubSubHandler = pubSubHandler; |
46 | 36 | this.nodeId = nodeId; |
47 | | - startSubscriber(); |
| 37 | + pubSubHandler.subscribe(this::handleMessage); |
48 | 38 | } |
49 | 39 |
|
50 | | - public void registerField(DataField<?> field) { |
| 40 | + // ==================== Auto-register fields on subscribe ==================== |
| 41 | + |
| 42 | + @Override |
| 43 | + public <T> void subscribe(DataField<T> field, PlayerDataListener<T> listener) { |
51 | 44 | fieldRegistry.put(field.fullKey(), field); |
| 45 | + super.subscribe(field, listener); |
52 | 46 | } |
53 | 47 |
|
54 | | - public void registerLinkType(LinkType<?> type) { |
| 48 | + @Override |
| 49 | + public <K, T> void subscribeLinked(DataField<T> field, LinkedDataListener<K, T> listener) { |
| 50 | + fieldRegistry.put(field.fullKey(), field); |
| 51 | + super.subscribeLinked(field, listener); |
| 52 | + } |
| 53 | + |
| 54 | + @Override |
| 55 | + public <K> void subscribeLinkChange(LinkType<K> type, LinkChangeListener<K> listener) { |
55 | 56 | linkTypeRegistry.put(type.name(), type); |
| 57 | + super.subscribeLinkChange(type, listener); |
| 58 | + } |
| 59 | + |
| 60 | + @Override |
| 61 | + public <T> void subscribeExpiration(ExpiringField<T> field, ExpirationListener<T> listener) { |
| 62 | + fieldRegistry.put(field.fullKey(), field); |
| 63 | + super.subscribeExpiration(field, listener); |
| 64 | + } |
| 65 | + |
| 66 | + @Override |
| 67 | + public <K, T> void subscribeLinkedExpiration(ExpiringLinkedField<K, T> field, LinkedExpirationListener<K, T> listener) { |
| 68 | + fieldRegistry.put(field.fullKey(), field); |
| 69 | + super.subscribeLinkedExpiration(field, listener); |
56 | 70 | } |
57 | 71 |
|
58 | 72 | // ==================== Override fire* to publish ==================== |
@@ -118,31 +132,7 @@ public <K, T> void fireLinkedExpired(ExpiringLinkedField<K, T> field, K linkKey, |
118 | 132 | // ==================== Pub/Sub ==================== |
119 | 133 |
|
120 | 134 | private void publish(EventMessage message) { |
121 | | - try (Jedis jedis = pool.getResource()) { |
122 | | - jedis.publish(channel, GSON.toJson(message)); |
123 | | - } |
124 | | - } |
125 | | - |
126 | | - private void startSubscriber() { |
127 | | - subscriberThread = new Thread(() -> { |
128 | | - while (running) { |
129 | | - try (Jedis jedis = pool.getResource()) { |
130 | | - activeSub = new JedisPubSub() { |
131 | | - @Override |
132 | | - public void onMessage(String ch, String msg) { |
133 | | - handleMessage(msg); |
134 | | - } |
135 | | - }; |
136 | | - jedis.subscribe(activeSub, channel); |
137 | | - } catch (Exception e) { |
138 | | - if (running) { |
139 | | - try { Thread.sleep(1000); } catch (InterruptedException ie) { break; } |
140 | | - } |
141 | | - } |
142 | | - } |
143 | | - }, "swofty-pubsub-subscriber"); |
144 | | - subscriberThread.setDaemon(true); |
145 | | - subscriberThread.start(); |
| 135 | + pubSubHandler.publish(GSON.toJson(message)); |
146 | 136 | } |
147 | 137 |
|
148 | 138 | @SuppressWarnings("unchecked") |
@@ -263,12 +253,6 @@ private Set<UUID> listToUuidSet(Object raw) { |
263 | 253 | // ==================== Lifecycle ==================== |
264 | 254 |
|
265 | 255 | public void shutdown() { |
266 | | - running = false; |
267 | | - if (activeSub != null) { |
268 | | - try { activeSub.unsubscribe(); } catch (Exception ignored) {} |
269 | | - } |
270 | | - if (subscriberThread != null) { |
271 | | - subscriberThread.interrupt(); |
272 | | - } |
| 256 | + pubSubHandler.shutdown(); |
273 | 257 | } |
274 | 258 | } |
0 commit comments