redux-kotlin icon indicating copy to clipboard operation
redux-kotlin copied to clipboard

Threading issues even with createThreadSafeStore

Open zackls opened this issue 3 years ago • 8 comments

Hi there! Recently began using this library, and have noticed some hard-to-reproduce errors popping up while developing. The errors occur inconsistently and mention threading issues:

You may not call store.subscribe() while the reducer is executing. If you would like to be notified after the store has been updated, subscribe from a component and invoke store.getState() in the callback to access the latest state. See https://www.reduxkotlin.org/api/store#subscribelistener-storesubscriber for more details. You may be seeing this due accessing the store from multiplethreads. Try createThreadSafeStore() https://reduxkotlin.org/introduction/threading

and

You may not call store.getState() while the reducer is executing. The reducer has already received the state as an argument. Pass it down from the top reducer instead of reading it from the store. You may be accessing getState while dispatching from another thread. Try createThreadSafeStore(). https://reduxkotlin.org/introduction/threading

However we do use createThreadSafeStore, and these errors are being thrown from code outside our reducers (in thunks and views), so I am surprised to see these errors.

We are using:

org.reduxkotlin:redux-kotlin-threadsafe:0.5.5
org.reduxkotlin:reselect:0.5.5
org.reduxkotlin:redux-kotlin-thunk:0.5.5

zackls avatar Apr 07 '21 21:04 zackls

Hey there! I'm investigating this issue with @zackls and after some debugging, we think that the cause for this error may be related to the createThreadSafeStore implementation and wanted to run that by you guys. For context, we were also using the redux-kotlin-thunk middleware, and our store implementation looked like:

val store = createThreadSafeStore(
  rootReducer,
  initialState,
  applyMiddleware(
    createThunkMiddleware(),
  )
)

With this implementation, it seems like middlewares are applied to enhance the store's dispatch function before the store's functions get synchronized. For us, this meant that our thunks were accessing a non-synchronized dispatch function, whereas outside of thunks, invocations to dispatch were synchronized. Since our application makes use of multiple threads and some invocations to dispatch were not synchronized, we were seeing the reported error indicating that we weren't using createThreadSafeStore.

We solved this in our application by creating a new store enhancer to handle synchronization, and ordering it so that store creation / synchronization happens before middlewares are applied. Something like:

fun <State> synchronizeStore(): StoreEnhancer<State> {
  return { storeCreator ->
    { reducer, initialState, en: Any? ->
      val store = storeCreator(reducer, initialState, en)
      val synchronizedStore = SynchronizedStore(store)
      synchronizedStore
    }
  }
}

val store = createStore(
  rootReducer,
  initialState,
    compose(
      applyMiddleware(
        createThunkMiddleware(),
      ),
      synchronizeStore(),
    ),
)

Happy to open a PR or discuss further if that all checks out!

jennkao avatar Apr 21 '21 16:04 jennkao

@jennkao Thanks for the explanation and sharing details. I have not ran into this myself. If you think this is something that would affect users of the library, PRs are welcome.

patjackson52 avatar May 01 '21 00:05 patjackson52

@patjackson52 Sure thing! I opened up a PR here: https://github.com/reduxkotlin/redux-kotlin/pull/78

jennkao avatar May 02 '21 20:05 jennkao

Fwiw I'm also experiencing this issue and also using the Redux Thunk middleware

tomtaila-wesayhi avatar Jun 14 '21 15:06 tomtaila-wesayhi

Same issue for us as well

ozeetee avatar Jun 16 '21 21:06 ozeetee

Any movement on this, or the PR? It's easy enough to drop the function in, but it'd be nice not to have to.

carterhudson avatar Aug 01 '21 18:08 carterhudson

Any movement on this, or the PR? It's easy enough to drop the function in, but it'd be nice not to have to.

PR looks good. I requested a small rename change. Hope to have it merged this week.

patjackson52 avatar Aug 02 '21 16:08 patjackson52

hey, are there any updates?

TobyEb avatar Sep 16 '21 13:09 TobyEb

Fix PR was merged. Is anyone still experiencing this issue or can it be closed?

mpetuska avatar Jan 16 '23 21:01 mpetuska

Hi @mpetuska, just wanted to try the new release but it isn't available on maven yet. I tried with: implementation "org.reduxkotlin:redux-kotlin-threadsafe-jvm:0.5.6" but the dependency can't be resolved.

TobyEb avatar Jan 24 '23 09:01 TobyEb

@TobyEb 0.6.0-SNAPSHOT is only on maven snapshot repositories so you'll need to add it separately like here https://github.com/reduxkotlin/redux-kotlin/blob/master/build-conventions/src/main/kotlin/convention.common.gradle.kts#L14

mpetuska avatar Jan 24 '23 10:01 mpetuska

As for released artefacts, looks like the latest is 0.5.5. There was never an 0.5.6 release.

https://repo.maven.apache.org/maven2/org/reduxkotlin/redux-kotlin-threadsafe-jvm/

mpetuska avatar Jan 24 '23 10:01 mpetuska

@TobyEb org.reduxkotlin:redux-kotlin-threadsafe-jvm:0.6.0 is now generally available on MavenCentral. Let me know if the issue is still present once you try it out.

mpetuska avatar Jan 29 '23 22:01 mpetuska

Closing due to inactivity. Reopen if the issue persists with the latest releases.

mpetuska avatar Jul 30 '23 19:07 mpetuska