Comments (5)
I can have a look this weekend, I'm planning to continue working on the current changes I did and maybe we can have some unit tests to reproduce this problem you faced.
But I was a bit afraid that always doing this "dispatch_async" on main queue could bring some problems eventually. We should check if we're already in the Main Queue and, in that case, instead of dispatching async simply run the block immediately. However, there's a difference between Main Queue and Main Thread, that is very well explained in here: https://blog.krzyzanowskim.com/2016/06/03/queues-are-not-bound-to-any-specific-thread/
In my code I usually have this extension:
extension Thread {
private static let dispatchSpecificKey = DispatchSpecificKey<UUID>()
private static let dispatchSpecificValue = UUID()
public static var isMainQueue: Bool {
guard let queueUUID = DispatchQueue.getSpecific(key: Thread.dispatchSpecificKey),
queueUUID == Thread.dispatchSpecificValue,
Thread.isMainThread else { return false }
return true
}
static func setMainQueueID() {
DispatchQueue.main.setSpecific(key: Thread.dispatchSpecificKey, value: Thread.dispatchSpecificValue)
}
}
Then I run Thread.setMainQueueID()
in the AppDelegate
to collect the queue id and then I can call:
if Thread.isMainQueue {
doSomething()
} else {
DispatchQueue.main.async {
doSomething()
}
}
I can try to do the same in the Store, but then the creating of the Store must be done in the Main Queue, so we collect the correct Queue ID, or can be dispatched only once if possible.
Can you please try that? Maybe you could open a PR in case this fixes for you and then maybe add some tests.
from swiftrex.
It's kinda similar to this approach here:
https://github.com/ReactiveX/RxSwift/blob/53cd723d40d05177e790c8c34c36cec7092a6106/Platform/DispatchQueue%2BExtensions.swift
from swiftrex.
I understand better now your problem, and indeed this behaviour is wrong and should be fixed, so when an event comes through the Store, its way from there to become handled by the reducer (considering that it was translated into an Action synchronously) should always happen in the very same loop of the same queue. So my proposed solution will very likely fix that and improve slightly the overall performance, although we hope no middleware will lock the main thread or whatever thread we choose this to happen, because it's gonna be a serial queue.
Ok, but what about the initial dispatch event? In your example you're dispatching two events in the same loop, one right after another. So the two events will arrive at the "same time" into the Store. If at this point the Store schedules async to the next runloop, the ViewController will finish the function immediately while the state is still outdated. If we also handle the event arrival using same strategy (immediate evaluation if in Main Queue), the ViewController will dispatch the first event, wait for the reducer and state update, then dispatch the second. Anyway they won't race with each other because the Queue is FIFO, but I wonder about the benefits of one or other model.
I currently tend to think that the event arrival should always DispatchQueue.main.async, while the other routings inside the Store should use the immediate evaluation strategy. But I'm open to suggestions.
I'll post the fix tomorrow in the master and write some new tests, release only in the 4th or 5th of October.
from swiftrex.
@AlexisQapa Hey! The develop
branch should fix your problem now, I also included a test that's basically the sample code you sent. Can you please validate that this behaviour now fixes your problem?
from swiftrex.
Fixed in develop, however the solution won't be necessary anymore in the new (and hopefully final) design, available in this PR: #40
After unifying events and actions, and making the separation of view events and store actions not in the design but as a possibility thanks to the strongly-typed ActionType
now, and also allowing lifting either Action
or State
for Middlewares, Reducers and also Stores (ViewStore is a proxied store limited to View Events and View State), the whole Queue-safety is much more clear. The only time we "bottleneck" actions is when they first enter the Store, coming from either Views or Middlewares. Once in the store, the action will travel through the Middleware pipeline, then through the Reducer pipeline in the very same runloop. That, of course, requires a correct implementation of Middlewares (never, I mean NEVER call next()
async), which should not be a hard thing to do.
Anyway, this model should be much safer and easy to implement.
from swiftrex.
Related Issues (20)
- middleware lift with WritableKeyPath doesn't work on AnyMiddleware HOT 2
- Fix animations from Middleware
- Dead-Letter Queue HOT 1
- Memory leak in LiftMiddleware
- When will develop be the official release? HOT 2
- Lift EffectMiddleware using KeyPath not receiving context
- How to modify AppLifecycleMiddleware to adopt the new MiddlewareProtocol? HOT 2
- Redundant conformance of 'ASAPScheduler' to protocol 'Scheduler'
- Using await/async in middleware HOT 4
- IO monad and stack limit HOT 6
- I think it's time to enable Enabling Concurrency warnings in Xcode HOT 2
- Dynamic store HOT 5
- Migrate away from Travis CI HOT 4
- Design question : Model to State migration HOT 2
- Dispatch actions and run reducers on background thread? HOT 4
- CombineRex : Unexpected PublisherType behavior HOT 3
- Trying to use Effect.promise with Firebase's DynamicLinkComponents.shortenURL HOT 5
- Question about assertionFailure() HOT 5
- How organize communication between different states HOT 2
- Improve Tests
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from swiftrex.