typelevel / typelevel/fs2

Unexpected interaction of `Pull.bracketCase` and `Stream`'s `flatMap`

Open
#3,118 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Scala
Stars
2.5k
Forks
636
Avg merge
2d 4h
Merged PRs (30d)
7

Description

Context

The fact that Stream[F, O] can be easily got from Pull[F, O, Unit] is severely used in this example.

Stream's bracket API does not allow the release action to emit output values, since it takes F[...], not Stream[F, ...]. But, Pull's bracket API does allow to emit values, since it takes Pull[F, O, Unit] as a release action.

Possibly unexpected situation

Consider now a situation when I have some effect after some emit in the release action of some bracket of some Pull. Now consider that I converted this to a Stream and flatMap'ed on it and in the RHS side of this flatMap an error occurs. You can see illustrating code for this. Do you expect an effect in the release action, which goes after the emit to occur? I did, at least at first, but actually, at least on v3.5.0 release action do not finish all its actions.

Later I realised that maybe this can be thought of as expected semantics since flatMap'ing on Streams actually means that we kinda insert intermediate actions instead of emits of a stream on LHS, so it this action fails, the whole stream fails no matter it is a release function. Kind of, you must watch (and maybe guard) your emits in the release action, if you have one.

Despite that, I had a little discussion with other developers who agreed that despite this explanation, they would expect all effects in the release action to be executed because of pragmatics of it.

Definitely unexpected situation

Okay, let's guard the final effectful action which should go after emit in the release action. To do this, let's make another bracket. You can see example of this change here. But, this bracket in the release action simply does not work as a bracket, and this is completely unexpected.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the two linked Scastie examples and read the Pull.bracketCase API alongside Stream.flatMap semantics. Determine whether release actions should complete after emitted values and downstream failure, then establish the expected behavior before changing implementation or tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
stream-processing
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.