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

Add pause and resume API's to Loop #17

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add pause and resume API's to Loop
On some scenarios, it's useful to "pause" the `Loop` so that we stop
processing events for some reason (e.g. to stop a `Loop` backed
Service). Following the same reasoning, it becomes necessary to have a
"resume" mechanism so that the Loop starts processing events again.

Given `Loop` now starts automatically and `stop` is designed as a tear
down mechanism to be used on dealloc and dispose all observations, some
new API's are required so that we can unplug/replug feedbacks to
achieve the above mentioned pause/resume behavior.

## Changes

- Create new `plugFeedbacks` and `unplugFeedbacks` API's in
`Floodgate`, which establish and dispose feedbacks observations,
respectively. Floodgate now retains the feedbacks passed in on
`bootstrap` to use them on `plugFeedbacks`.

- Add `pause` and `resume` API's to `LoopBoxBase`.

- Implement `pause` and `resume` API's in `RootLoopBox`, which unplug
and plug the feedbacks on the `Floodgate`, respectively.

- Implement `pause` and `resume` API's in `ScopedLoopBox`, which
forward the calls to their root, respectively.
  • Loading branch information
p4checo committed Jul 21, 2020
commit 288a626f07737caa9b1ad225138d23a43147c829
14 changes: 13 additions & 1 deletion Loop/Floodgate.swift
Original file line number Diff line number Diff line change
@@ -34,7 +34,8 @@ final class Floodgate<State, Event>: FeedbackEventConsumer<Event> {

private let queue = Atomic(QueueState())
private let reducer: (inout State, Event) -> Void
private let feedbackDisposables = CompositeDisposable()
private var feedbacks: [Loop<State, Event>.Feedback] = []
private var feedbackDisposables = CompositeDisposable()

init(state: State, reducer: @escaping (inout State, Event) -> Void) {
self.state = state
@@ -46,6 +47,12 @@ final class Floodgate<State, Event>: FeedbackEventConsumer<Event> {
}

func bootstrap(with feedbacks: [Loop<State, Event>.Feedback]) {
self.feedbacks = feedbacks

plugFeedbacks()
}

func plugFeedbacks() {
for feedback in feedbacks {
// Pass `producer` which has replay-1 semantic.
feedbackDisposables += feedback.events(
@@ -60,6 +67,11 @@ final class Floodgate<State, Event>: FeedbackEventConsumer<Event> {
}
}

func unplugFeedbacks() {
p4checo marked this conversation as resolved.
Show resolved Hide resolved
feedbackDisposables.dispose()
feedbackDisposables = CompositeDisposable()
}

override func process(_ event: Event, for token: Token) {
enqueue(event, for: token)

20 changes: 20 additions & 0 deletions Loop/LoopBox.swift
Original file line number Diff line number Diff line change
@@ -44,6 +44,14 @@ internal class ScopedLoopBox<RootState, RootEvent, ScopedState, ScopedEvent>: Lo
event: { [eventTransform] in eventTransform(event($0)) }
)
}

override func pause() {
root.pause()
p4checo marked this conversation as resolved.
Show resolved Hide resolved
}

override func resume() {
root.resume()
}
}

internal class RootLoopBox<State, Event>: LoopBoxBase<State, Event> {
@@ -83,6 +91,14 @@ internal class RootLoopBox<State, Event>: LoopBoxBase<State, Event> {
ScopedLoopBox(root: self, value: scope, event: event)
}

override func pause() {
floodgate.unplugFeedbacks()
}

override func resume() {
floodgate.plugFeedbacks()
}

func start(with feedbacks: [Loop<State, Event>.Feedback]) {
floodgate.bootstrap(with: feedbacks + [input.feedback])
}
@@ -115,6 +131,10 @@ internal class LoopBoxBase<State, Event> {
) -> LoopBoxBase<S, E> {
subclassMustImplement()
}

func pause() { subclassMustImplement() }

func resume() { subclassMustImplement() }
}

@inline(never)
8 changes: 8 additions & 0 deletions Loop/Public/Loop.swift
Original file line number Diff line number Diff line change
@@ -69,6 +69,14 @@ public final class Loop<State, Event> {
box: box.scoped(to: { $0 }, event: { _ in fatalError() })
)
}

public func pause() {
box.pause()
}

public func resume() {
box.resume()
}
}

extension Loop {