Skip to content

Commit

Permalink
app: Improve IPC loop guards
Browse files Browse the repository at this point in the history
  • Loading branch information
evanpurkhiser committed Dec 30, 2020
1 parent 0538ab7 commit c0c0b45
Showing 1 changed file with 17 additions and 21 deletions.
38 changes: 17 additions & 21 deletions src/shared/store/ipc.ts
Expand Up @@ -47,6 +47,11 @@ type SerializedChange = {

type ChangeHandler = (change: SerializedChange) => void;

/**
* Mark when we're applying a UI config change via IPC to avoid a loop over IPC.
*/
let isApplyingConfigChange = false;

/**
* Maintains a list of handlers that will be called in response to a serailized
* change in the store.
Expand Down Expand Up @@ -285,38 +290,31 @@ export const registerMainIpc = () => {
event.sender.send('store-init', serialize(AppStore, store));

// Register this window to recieve store changes over ipc
changeHandlers.push(change => event.sender.send('store-update', change));
changeHandlers.push(
change => !isApplyingConfigChange && event.sender.send('store-update', change)
);
});

// Register listener for config object changes
ipcMain.on('config-update', (_e, change: SerializedChange) => applyStoreChange(change));
ipcMain.on('config-update', (_e, change: SerializedChange) => {
isApplyingConfigChange = true;
applyStoreChange(change);
isApplyingConfigChange = false;
});

// Save any updates to the configuration store
deepObserve(store.config, () => settings.set(serialize(AppConfig, store.config)));
};

/**
* XXX: This list MAY be brittle as it is what stops us from getting stuck in an
* update loop upon config changes.
*
* Becuase changes will be propagated from the client -> main, and then back
* from main -> client, we need to ignore the changes we just made.
*/
const recentConfigChanges = new Set<string>();

/**
* Register this window to have it's store hydrated and synced from the main
* process' store.
*/
export const registerRendererIpc = () => {
ipcRenderer.on('store-update', (_, change: SerializedChange) => {
// When recieving configuration changes, drop changes that were jsut made.
if (change.path.startsWith('config') && recentConfigChanges.has(change.path)) {
setTimeout(() => recentConfigChanges.delete(change.path), 500);
return;
}

isApplyingConfigChange = change.path.startsWith('config');
applyStoreChange(change);
isApplyingConfigChange = false;
});

ipcRenderer.on('store-init', (_, data: any) => {
Expand All @@ -335,10 +333,8 @@ export const registerRendererConfigIpc = () =>
observeStore({
target: store.config,
prefix: 'config',
handler: change => {
recentConfigChanges.add(change.path);
ipcRenderer.send('config-update', change);
},
handler: change =>
!isApplyingConfigChange && ipcRenderer.send('config-update', change),
});

/**
Expand Down

0 comments on commit c0c0b45

Please sign in to comment.