From ec1954bae1d56308267306774521c79ea2029905 Mon Sep 17 00:00:00 2001 From: catbref Date: Wed, 24 Jun 2020 11:22:26 +0100 Subject: [PATCH] Notify Chat websocket listeners if group membership changes Also unified newTransactionExecutor and newBlockExecutor into callbackExecutor. --- .../org/qortal/controller/ChatNotifier.java | 5 ++++ .../org/qortal/controller/Controller.java | 29 ++++++++++++++++--- src/main/java/org/qortal/group/Group.java | 5 ++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/qortal/controller/ChatNotifier.java b/src/main/java/org/qortal/controller/ChatNotifier.java index 3517ce80..57ca7cbf 100644 --- a/src/main/java/org/qortal/controller/ChatNotifier.java +++ b/src/main/java/org/qortal/controller/ChatNotifier.java @@ -40,4 +40,9 @@ public class ChatNotifier { listener.notify(chatTransactionData); } + public synchronized void onGroupMembershipChange() { + for (Listener listener : this.listenersBySession.values()) + listener.notify(null); + } + } diff --git a/src/main/java/org/qortal/controller/Controller.java b/src/main/java/org/qortal/controller/Controller.java index ea410c86..9f9b80de 100644 --- a/src/main/java/org/qortal/controller/Controller.java +++ b/src/main/java/org/qortal/controller/Controller.java @@ -125,10 +125,10 @@ public class Controller extends Thread { private final long buildTimestamp; // seconds private final String[] savedArgs; - private ExecutorService newTransactionExecutor = Executors.newSingleThreadExecutor(); + private ExecutorService callbackExecutor = Executors.newFixedThreadPool(3); + private volatile boolean notifyGroupMembershipChange = false; private volatile BlockData chainTip = null; - private ExecutorService newBlockExecutor = Executors.newSingleThreadExecutor(); private long repositoryBackupTimestamp = startTime; // ms private long ntpCheckTimestamp = startTime; // ms @@ -733,6 +733,22 @@ public class Controller extends Thread { System.exit(0); } + // Callbacks + + public void onGroupMembershipChange(int groupId) { + /* + * We've likely been called in the middle of block processing, + * so set a flag for now as other repository sessions won't 'see' + * the group membership change until a call to repository.saveChanges(). + * + * Eventually, onNewBlock() will be executed and queue a callback task. + * This callback task will check the flag and notify websocket listeners, etc. + * and those listeners will be post-saveChanges() and hence see the new + * group membership state. + */ + this.notifyGroupMembershipChange = true; + } + // Callbacks for/from network public void doNetworkBroadcast() { @@ -759,17 +775,22 @@ public class Controller extends Thread { requestSysTrayUpdate = true; // Broadcast our new height info and notify websocket listeners - this.newBlockExecutor.execute(() -> { + this.callbackExecutor.execute(() -> { Network network = Network.getInstance(); network.broadcast(peer -> network.buildHeightMessage(peer, latestBlockData)); BlockNotifier.getInstance().onNewBlock(latestBlockData); + + if (this.notifyGroupMembershipChange) { + this.notifyGroupMembershipChange = false; + ChatNotifier.getInstance().onGroupMembershipChange(); + } }); } /** Callback for when we've received a new transaction via API or peer. */ public void onNewTransaction(TransactionData transactionData, Peer peer) { - this.newTransactionExecutor.execute(() -> { + this.callbackExecutor.execute(() -> { // Notify all peers (except maybe peer that sent it to us if applicable) Network.getInstance().broadcast(broadcastPeer -> broadcastPeer == peer ? null : new TransactionSignaturesMessage(Arrays.asList(transactionData.getSignature()))); diff --git a/src/main/java/org/qortal/group/Group.java b/src/main/java/org/qortal/group/Group.java index 96c026b5..1dbb18b0 100644 --- a/src/main/java/org/qortal/group/Group.java +++ b/src/main/java/org/qortal/group/Group.java @@ -8,6 +8,7 @@ import java.util.Map; import org.qortal.account.Account; import org.qortal.account.PublicKeyAccount; +import org.qortal.controller.Controller; import org.qortal.crypto.Crypto; import org.qortal.data.group.GroupAdminData; import org.qortal.data.group.GroupBanData; @@ -140,6 +141,8 @@ public class Group { private void addMember(String member, long joined, byte[] reference) throws DataException { GroupMemberData groupMemberData = new GroupMemberData(this.groupData.getGroupId(), member, joined, reference); groupRepository.save(groupMemberData); + + Controller.getInstance().onGroupMembershipChange(this.groupData.getGroupId()); } private void addMember(String member, TransactionData transactionData) throws DataException { @@ -153,6 +156,8 @@ public class Group { private void deleteMember(String member) throws DataException { groupRepository.deleteMember(this.groupData.getGroupId(), member); + + Controller.getInstance().onGroupMembershipChange(this.groupData.getGroupId()); } // Adminship