Comments (6)
@leandromperez,
It would be nice if you can isolate your code and post it here.
Could it be possible that this method: ... mutates concurrently the state, therefore the dictionary, creating duplicate entries?
No, this method executes blocks in a serial fashion.
from rxfeedback.swift.
Hi @eliekarouz,
Thanks for your answer.
This is a really condensed version of the code, there are many different parts to it, but this is mostly what's related to the feedback loop:
struct ClassesStateMachine{
//This is the State
...
}
extension ClassesStateMachine {
typealias FeedbackLoop = (Driver<ClassesStateMachine>) -> Signal<ClassesStateMachine.Event>
struct Feedback {
//This is the system driver, a reduced version of it
static func statemachineFeedbackDriver(_ interactor: ClassesInteractorImp) -> Driver<ClassesStateMachine> {
return Driver.system(initialState: ClassesStateMachine.initialState,
reduce: ClassesStateMachine.reduce,
feedback:
Feedback.uiFeedback(interactor),
Feedback.processInteractions(interactor))
}
//This is the feedback that will analyze the state and respond with a service execution. E.g. when the user interacts with the screen, like tapping a button to execute some logic in the backend.
//It returns a Set of Statemachine to avoid cancelling pending services of previous loops (i.e. interactios generated in previous Statemachines)
private static func processInteractions(_ interactor: ClassesInteractorImp) -> ClassesStateMachine.FeedbackLoop {
let interactionToProcess : (ClassesStateMachine) -> Set<ClassesStateMachine> = { statemachine in
if statemachine.interactionToProcess != nil {
return Set([statemachine])
}
return Set()
}
let processInteraction : (ClassesStateMachine) -> Signal<ClassesStateMachine.Event> = { (statemachine) in
return interactor.executeInteraction(of:statemachine)
}
return react(requests: interactionToProcess, effects: processInteraction)
}
//This binds te UI with the state
private static func uiFeedback(_ interactor : ClassesInteractorImp) -> ClassesStateMachine.FeedbackLoop {
return bind {[unowned interactor] stateMachine in
let subscriptions = [
stateMachine.drive(interactor.presenter.statemachineInput),
]
let events : [Signal<ClassesStateMachine.Event>] = [ interactor.viewController.userEvents]
return Bindings(subscriptions: subscriptions, events: events)
}
}
}
}
extension ClassesInteractorImp {
//An interaction is an action that the user can perform on the screen, containing the necessary data to execute a service
func executeInteraction( of statemachine:ClassesStateMachine) -> Signal<ClassesStateMachine.Event> {
guard let interaction = statemachine.interactionToProcess else {fatalError("The statemachine must have an interaction")}
let service = self.service(for:interaction, of: statemachine)
return service.asSignal(onErrorRecover: { .just( ClassesStateMachine.Event.didFail(interaction, error:$0)) })
}
//This will perform a service, i.e. talk to the backend, and create an event when the response is obtained.
func service(for interaction: ClassesStateMachine.Interaction, of statemachine: ClassesStateMachine) -> Observable<ClassesStateMachine.Event>{
switch interaction {
case .doSomething :
return doSomething(with: statemachine) // talks to the backend to doSomething and returns an Event in response
...
}
}
I was thinking that maybe more than one effect was mutating that dictionary concurrently, because I cannot think of another way of inserting a second object with an existing key into that dictionary.
We're not calling this function directly: public func react<State, Request: Equatable, RequestID, Event>( requests: @escaping (State) -> [RequestID: Request], effects: @escaping (_ initial: Request, _ state: Observable<Request>)
We're calling this one: public func react<State, Request, Event>( requests: @escaping (State) -> Set<Request>, effects: @escaping (Request) -> Signal<Event> )
I hope this information is useful somehow,
Thanks again,
Leandro
from rxfeedback.swift.
@leandromperez How are you declaring hashable/equatable for the ClassesStateMachine
. Could it be that you have by mistake reference types that are being mutated AND used to compute the hash or ==
from rxfeedback.swift.
struct ClassesStateMachine {
var id : Int
}
extension ClassesStateMachine: Equatable {}
func == (lhs: ClassesStateMachine, rhs: ClassesStateMachine) -> Bool {
return lhs.id == rhs.id
}
Sometimes the reducer returns a StateMachine that doesn't mutate the id, to avoid repeating some effects in the next loop. I don't see how that could cause that crash, but do you think it might be a problem?
from rxfeedback.swift.
@leandromperez ,
Please check this line:
https://github.com/apple/swift/blob/f978cb0ba32acad5cc434331fa6a6b0c39ea9358/stdlib/public/core/NativeDictionary.swift#L449
Try to look in your code for classes (reference types) not enums or structs (value types)... Most probably you are mutating the variables inside these classes which is causing this crash.
FYI this code crashes with a similar error because the class XString
is being mutated...
class XString: Hashable, Equatable {
static func == (lhs: XString, rhs: XString) -> Bool {
return lhs.string == rhs.string
}
var string: String
init(_ string: String) {
self.string = string
}
func hash(into hasher: inout Hasher) {
hasher.combine(string)
}
}
struct FakeValueType: Hashable, Equatable {
let xstring: XString
}
func test() {
let str1 = FakeValueType(xstring: XString("SomeString"))
var dict = [str1: 0]
for i in 0...100 {
str1.xstring.string = "Mutation\(i) for SomeString"
dict[str1] = i
}
}
from rxfeedback.swift.
@eliekarouz That makes sense.
If I understood correctly, the problem comes when the struct (that's used as the dictionary key) is associated with a reference type instance, and when such instance is used to calculate the hash value.
I couldn't find a reference type instance inside the graph of associations that are used inside the hash function. But anyways, there might be one hidden somewhere I've missed.
So, I've changed the hashing code so it depends only on the identifier that's used inside the equals function. Hopefully, that will fix the issue.
I can close this ticket and re-open it if necessary,
Thanks for your help!
from rxfeedback.swift.
Related Issues (20)
- Please update the examples in the README HOT 2
- Problem building dependencies of the example app. HOT 6
- RxFeedback example PlayCatch not working HOT 1
- Add more example about the new react function
- GithubPaginatedSearch example bug
- RxFeedback functions autocomplete problem HOT 2
- Ambiguous reference to member 'system(initialState:reduce:scheduler:feedback:)'
- The printing is printed only after network request is done.
- How can I fix this warning HOT 1
- Non-equatable requests in 2.0 HOT 6
- [Proposal] Introduce ObservableSystem make system chainable. HOT 3
- How to test the Event creation?
- [Proposal] React for Void?
- bind(self) { ... } leaks HOT 4
- [Request] Could you port RxFeedback to Combine HOT 2
- Carthage for macOS HOT 1
- New Release Tag HOT 11
- [Xcode 15 RC1 Bag] Names conflict HOT 5
- Cannot call value of non-function type '[Observable<Event>.Type]' HOT 2
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 rxfeedback.swift.