Skip to content

Conversation

@iampatbrown
Copy link
Contributor

Possible fix for #946
Main issue with PassthroughSubject is that it could only forward 1 value from an upstream PassthroughSubject, ie. nested cancellable effects. This should fix that by subscribing directly to the upstream publisher.

@iampatbrown iampatbrown marked this pull request as draft January 6, 2022 03:06
environment: environment
)

store.send(.recordButtonTapped)
Copy link
Contributor Author

@iampatbrown iampatbrown Jan 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.recordButtonTapped ends up returning a merged effect

return .merge(
environment.audioRecorder.startRecording(url)
.catchToEffect(VoiceMemosAction.audioRecorder),
Effect.timer(id: TimerId(), every: 1, tolerance: .zero, on: environment.mainRunLoop)
.map { _ in .currentRecordingTimerUpdated }
)

using RunLoop.immediate results in a failed test because .currentRecordingTimerUpdated now also gets received once before .audioRecorder(.failure(.couldntActivateAudioSession)) is received. I'm unsure if this is an undesired result of the change.

Adding the following test to TimerTests.swift demonstrates the difference in behaviour.

 func testTimerImmediate() {
    let scheduler = DispatchQueue.immediate

    var count = 0

    Effect.timer(id: 1, every: .seconds(1), on: scheduler)
      .sink { _ in count += 1 }
      .store(in: &self.cancellables)

    XCTAssertNoDifference(count, 1) // This PR

    // XCTAssertNoDifference(count, 0) // Current implementation
  }

Copy link
Contributor Author

@iampatbrown iampatbrown Jan 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the current implementation, the timer is triggered as soon as the PassThroughSubject subscribes to it, essentially dropping the value before the effect is subscribed to downstream.

let subject = PassthroughSubject<Output, Failure>()
let cancellable = self.subscribe(subject)

So the timer auto connects and outputs a value at line 37 which is lost before returning the effect.

In this PR the timer auto connects at .sink { _ in count += 1 }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting find! I think overall this PR is an improvement in the expectation that at least 1 thing emits from a timer running on an immediate scheduler, even if it is a breaking change.

@iampatbrown iampatbrown marked this pull request as ready for review January 6, 2022 04:30
Copy link
Member

@stephencelis stephencelis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @iampatbrown! Thanks for digging into the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants