Fixer of explicitly unwrapped optionals

Apple's Combine and reactive programming with Back pressure

Added on by Paul Wood.

When Apple released Combine in June 2019 those of use using RxSwift already felt justified if not vindicated that we had been making the right architectural decisions. This new framework, built into the foundation of the platform is going to increase the number of developers using reactive methods to solve problems exponentially and help the developer community as a whole solve problems in a consistent manner with less code.

I don’t want to give a rundown of what Combine and Reactive programming are. Nor do I want to compare and contrast Combine with RxSwift, which was my chosen flavor of Reactive Programming on Apple’s platforms before Combine. Please check out Casey Liss’s article for an overview of Combine. And if you are more an auditory learner check out Casey and John Sundell on the Swift by Sundell podcast.

I wanted to deep dive into something Combine has and RxSwift does not, Back pressure. This is a feature of Combine that allows a communication flow both up and down a reactive chain. That data flow is best considered, Elements move down the stream and Demand is returned up the stream to signify if more work can be done.

Everything is mental models when learning a new concept. After playing with the new API’s a little mental model for the different moving parts of Combine that deal with back pressure came to me, Marbles in a Funnel

At this point if you haven’t been to RxMarbles.com you are doing yourself a disservice, go check that site out first. Marbles are a great mental model for elements of a stream. They flow and roll place to place but they are also one unit and concrete unlike a stream of water. Mental models using liquids don’t stick for me when thinking about back pressure because there is not a single “unit” of water. A more humorous mental model for elements combining the two could be a lazy river or rafting ride with lots of people in inner-tubes flowing through turbulent water features.

Marble, Element - an element published by a Publisher

Marble, Element - an element published by a Publisher

Funnel, Publisher - represents work that can be done but a publisher, such as reading a line from a CSV file

Funnel, Publisher - represents work that can be done but a publisher, such as reading a line from a CSV file

Tube, Buffer - a tube that stacks up elements

Tube, Buffer - a tube that stacks up elements

Gate, Subscriber - the number of elements that a subscriber can handle. How many marbles would come out each time I opened it? The value returned by the subscriber for Demand can be thought of as the width of this gate creating back pressure so the marbles stay in the buffer

Gate, Subscriber - the number of elements that a subscriber can handle. How many marbles would come out each time I opened it? The value returned by the subscriber for Demand can be thought of as the width of this gate creating back pressure so the marbles stay in the buffer

Bringing it all together

I wrote up an example project that I hope will help others experiment with back pressure with a real world use case. You can find it on Github as PaulWoodiii/Combine-Backpressure-Research-CSV.

In the example project the “marbles” are rows in a Comma Separated Value file. each new row is sent down a reactive chain to a subscriber that does some work. As part of the published values a simple mapping from an array of Strings to a value type “NameType” helps us see how data can be transformed from a raw text file to a usable data structure that can be rendered in a User interface, or saved to a database.

I’ve added a simulation of back pressure by creating my own Subscriber based on Sink called SlowSink that sleeps the thread for some time. This creates back pressure and using breakpoints a developer can see when work is done. I’ve shared a few breakpoints in the project file to get readers started.

I hope this helps other developers get started learning how back pressure in reactive steams can be used, debugged and tested. However I know it is not complete and would recommend anyone who wants to really dive into the deep end to read documentation on back pressure written for RxJava.

I can assume that Apple has been working on Combine for client side development for ease of use when it comes to developing asynchronous code. RxSwift got along very well without back pressure for client side development though. My suspicion is that the inclusion of back pressure hints that Apple is aware of its utility for server side development. With back pressure developers can read massive files, while keeping a low memory footprint.