Chapter 18: Custom Publishers & Backpressure

I couldn’t figure out this, in the ShareReplay Publisher(Transformer to be more precise) when I finished I’ve got this output:

shareReplay: receive subscription: (PassthroughSubject)
shareReplay: request unlimited
shareReplay: receive value: (1)
+0.04658s: subscription1 received 1
shareReplay: receive value: (2)
+0.04791s: subscription1 received 2
shareReplay: receive value: (3)
+0.04878s: subscription1 received 3
+0.05000s: subscription2 received 2
+0.05009s: subscription2 received 3
shareReplay: receive value: (4)
+0.05055s: subscription1 received 4
+0.05080s: subscription2 received 4
shareReplay: receive value: (5)
+0.05166s: subscription1 received 5
+0.05192s: subscription2 received 5
shareReplay: receive finished
+0.05359s: subscription1 completed: finished
+0.05383s: subscription2 completed: finished
Subscribing to shareReplay after upstream completed
+1.05626s: subscription3 received 4
+1.05640s: subscription3 received 5
+1.05695s: subscription3 completed: finished

1. Why didn’t the subscription 2 get value 1, and subscription 3 get 1,2,3. Even if I set the capacity to 20, it will support all values of the example(we just sent 5 values through the subject).

2. We never delete data from our replay variable inside the ShareReplay class, so when a new subscription is created we pass this array to it and there when that receives a new input from upstream we can send the values inside the buffer variable(ShareReplaySubscription) + the new value. I don’t get, why are there some values not delivered to the the subscription(just the first is the only one that gets all)?.

Is it possible to explain in a detailed way?

@fpillet Can you please help with this when you get a chance? Thank you - much appreciated! :]

Hi @elichigo,

  1. In the book example and in the code you type all along the shareReplay section, the publisher you create replays the last two items upon subscription. Since the example code emits three items before you create subscription2, it is normal that this subscription only gets the last two items the publisher emitted before you subscribe.

I will double check the code that we have in the book for any mistake, because running the final version of the project yields the correct results (with one gotcha – I mistakenly print “subscription2” instead of “subscription1” in the subscription1 subscription – fixing this for the next iteration of the book)

I also tested the publisher with a replay value set to 20 and it worked as expected (make sure you click in the text area and scroll down in your browser to see all output):

shareReplay: receive subscription: (PassthroughSubject)
shareReplay: request unlimited
shareReplay: receive value: (1)
+0.03541s: subscription1 received 1
shareReplay: receive value: (2)
+0.03619s: subscription1 received 2
shareReplay: receive value: (3)
+0.03671s: subscription1 received 3
+0.03740s: subscription2 received 1
+0.03746s: subscription2 received 2
+0.03751s: subscription2 received 3
shareReplay: receive value: (4)
+0.03781s: subscription1 received 4
+0.03798s: subscription2 received 4
shareReplay: receive value: (5)
+0.03853s: subscription1 received 5
+0.03870s: subscription2 received 5
shareReplay: receive finished
+0.03971s: subscription1 completed: finished
+0.03986s: subscription2 completed: finished
Subscribing to shareReplay after upstream completed
+1.13669s: subscription3 received 1
+1.13679s: subscription3 received 2
+1.13684s: subscription3 received 3
+1.13689s: subscription3 received 4
+1.13694s: subscription3 received 5
+1.13725s: subscription3 completed: finished
  1. You effectively do remove data from the replay variable in the ShareReplay class. Look for step // 30 in the book:
  // 30
  replay.append(value)
  if replay.count > capacity {
    replay.removeFirst()
  }

Every time you receive a new value and the buffer is already at capacity, you drop the first item.

Hope this helps,
Florent

I think there is also an error in the code, at least in my version (Page 373, I also checked online).
The code snippet says:

let subscription1 = publisher.sink(
  receiveCompletion: {
    print("subscription2 completed: \($0)", to: &logger)
  },
  receiveValue: {
    print("subscription2 received \($0)", to: &logger)
  }
)

and it should print “subscription1”. The log above also writes “subscription1”. Was this error perhaps introduced at a later point in time? Or am I getting something wrong?