Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broadcast channels not systematically closed ? Leak ? #128

Open
odusseys opened this issue Feb 9, 2022 · 3 comments
Open

Broadcast channels not systematically closed ? Leak ? #128

odusseys opened this issue Feb 9, 2022 · 3 comments

Comments

@odusseys
Copy link

odusseys commented Feb 9, 2022

I am running into a very strange bug, which I am having trouble reproducing consistently.
For background I am using the initStateWithPrevTab' helper to reinitialize state with previous tabs upon page load. My overall code looks like this (I have only one reducer, dataFetching`, and corresponding actions which only act on that reducer, which are whitelisted by redux-state-sync)

const persistConfig: PersistConfig<RootState> = {
  key: "root",
  storage,
  timeout: 0,
  stateReconciler: autoMergeLevel1,
  blacklist: ["dataFetching"],
};

const persistedReducer = persistReducer(
  persistConfig,
  withReduxStateSync(rootReducer) as any
);


const dataFetchingSync = createStateSyncMiddleware({
  whitelist: DATA_FETCHING_ACTION_TYPES,
});

export const store = createStore(
  persistedReducer,
  applyMiddleware(logger, dataFetchingSync)
);

initStateWithPrevTab(store);

Occasionally, I will run into issues when reloading a page where the redux state is immediately reset to its previous value, including the non-persisted reducer, which seemed strange.
Upon investigation, what happens is the following

  • Upon page load, a &_GET_INIT_STATE action is dispatched
  • Immediately after, a &_RECEIVE_INIT_STATE is received, with the same window uuid, and the previous value for the state, before reload
  • the state is thus overriden by that value

This means that there is no way, when that happens, to refresh the state in memory. Closing all tabs does not resolve it. Closing Chrome, however, does - and no more _RECEIVE_INIT_STATE action is received

I cannot reproduce this consistently and it happens randomly.
I cannot see a simple explanation for this, but I don't understand how, after reload, the state can still be available somewhere, and dispatched through the BroadcastChannel. I can't find a trace of that state anywhere in application storage so it must be in memory.
I am wondering if, by any chance, the BroadcastChannel created is not being closed upon reload, thus leading to a leak where, after reloading, it is still present with its original listener, and dispatches a state which has been kept in memory.
The BroadCastChannel API docs explicitly say that the channel should be closed when no longer used in order to avoid memory leaks. This does not seem to be the case in the source code. Should there perhaps be a listener for window.unload to close the channel ?

@aohua
Copy link
Owner

aohua commented Feb 9, 2022

Hi @odusseys Could you try using localstorage as the communication channel between tabs? If the issue still appears, it might be something wrong with BroadcastChannel, but I feel by the time you reload the BroadcastChannel should be closed and reopened.

@odusseys
Copy link
Author

I'm not sure it is.
https://github.com/pubkey/broadcast-channel#close-the-channel-if-you-do-not-need-it-anymore

Now, on browsers which support BrodcastChannel, the lib uses the native, API. This also requires the channel to be closed to allow for garbage collection
https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel/close

So I think a listener for window.unload which closes the channel connection would be necessary here

@mkdudeja
Copy link

Hello Everyone,

Any luck with above issue? Facing a similar issue where my only opened tab somehow gets synced with some other and causing the state to be replaced with earlier version. And, its intermittent.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants