Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
Event backlog (#18)
Browse files Browse the repository at this point in the history
* Don’t update scoped state while sending events

* Add Package.resolved

* Pass ref

* Event backlog
  • Loading branch information
reddavis authored Mar 19, 2022
1 parent b1c2eaa commit 9be06fa
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
*.perspectivev3
!default.perspectivev3
xcuserdata
profile
*.moved-aside
DerivedData
.idea/
Expand All @@ -19,3 +18,4 @@ Carthage/Checkouts/*
Carthage/Build/*
/fastlane/report.xml
/.ruby-version
*.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
36 changes: 27 additions & 9 deletions RedUx/Source/Store.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public final class Store<State, Event, Environment> {
private let middlewares: [AnyMiddleware<Event, Event, State>]
private var middlewareTasks: [Task<Void, Error>] = []

private var eventBacklog: [Event] = []
private var isProcessingEvent = false

// MARK: Initialization

/// Construct a Store with state, reducer and environment.
Expand Down Expand Up @@ -70,16 +73,30 @@ public final class Store<State, Event, Environment> {
/// Send an event through the store's reducer.
/// - Parameter event: The event.
public func send(_ event: Event) {
let eventStream = self.reducer(&self.state, event, self.environment)
self.eventBacklog.append(event)
guard !self.isProcessingEvent else { return }

Task {
for middleware in self.middlewares {
await middleware.execute(event: event, state: { self.state })
}
self.isProcessingEvent = true
var state = self.state

defer {
self.isProcessingEvent = false
self.state = state
}

while !self.eventBacklog.isEmpty {
let event = self.eventBacklog.removeFirst()
let eventStream = self.reducer(&state, event, self.environment)

guard let eventStream = eventStream else { return }
for await event in eventStream {
self.send(event)
Task { [state] in
for middleware in self.middlewares {
await middleware.execute(event: event, state: { state })
}

guard let eventStream = eventStream else { return }
for await event in eventStream {
self.send(event)
}
}
}
}
Expand Down Expand Up @@ -118,8 +135,9 @@ extension Store {
) -> Store<ScopedState, ScopedEvent, ScopedEnvironment> {
let scopedStore = Store<ScopedState, ScopedEvent, ScopedEnvironment>(
state: toScopedState(self.state),
reducer: .init { _, event, _ in
reducer: .init { state, event, _ in
self.send(fromScopedEvent(event))
state = toScopedState(self.state)
return .none
},
environment: toScopedEnvironment(self.environment),
Expand Down

0 comments on commit 9be06fa

Please sign in to comment.