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

SpliceFlatStreamToMetaSingle: propagate cancel when races with data #3036

Merged
merged 9 commits into from
Aug 14, 2024

Conversation

idelpivnitskiy
Copy link
Member

@idelpivnitskiy idelpivnitskiy commented Aug 8, 2024

Motivation:

Cancellation of the single may race with delivering the first element. If cancel wins, we already deliver CancellationException if someone subscribes to the payload publisher. However, if cancel arrives after dataSubscriber.onSuccess(...) and before someone subscribes to the payload publisher, it's a strong indicator that there was a race and dataSubscriber is not interested in it anymore. Therefore, we should pessimistically assume that nobody will ever subscribe to the payload publisher, cancel upstream subscription, and deliver CancellationException is someone still subscribes.

Modifications:

  • Cancel upstream subscription for both null and PENDING states if received data cancel;
  • Upwrap code around parent.packer.apply to assert that this path happens only if CANCELED;
  • Deliver CancellationException is someone still subscribes to the payload publisher after CANCELED;
  • Fix another bug: do not deliver dataSubscriber.onError if metaSeenInOnNext == true because it's already terminated (CANCELED does not play any role here);
  • Log more appropriate message if upstream delivers a terminal event after payloadSubscriber is already terminated (EMPTY_COMPLETED_DELIVERED);
  • Remove duplication around "Duplicate Subscribers are not allowed";

Result:

Network resources receive cancel signal and clean up connection state.


Note that the original version of this operator had this behavior, but it was changed in 38e2c67
We don't have a full PR for that commit with review comments. Based on the commit description I believe it was fixing a different problem and the change in cancel propagation behavior for PENDING state is likely a side-effect of introducing a new state.

@idelpivnitskiy idelpivnitskiy self-assigned this Aug 8, 2024
@idelpivnitskiy idelpivnitskiy marked this pull request as draft August 8, 2024 23:23
@idelpivnitskiy idelpivnitskiy marked this pull request as ready for review August 9, 2024 17:34
Copy link
Member Author

@idelpivnitskiy idelpivnitskiy left a comment

Choose a reason for hiding this comment

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

Ready for review, but will be merged only after Single.ambWith(...) fix

@@ -67,6 +68,7 @@
import static org.hamcrest.Matchers.startsWith;
import static org.junit.jupiter.api.Assertions.assertThrows;

@Disabled // FIXME: remove before merging
Copy link
Member Author

Choose a reason for hiding this comment

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

This PR is blocked by awaiting a fix for Single.ambWith(...) operator

if (maybePayloadSubUpdater.compareAndSet(this, null, CANCELED)) {
final Object current = maybePayloadSubUpdater.getAndUpdate(this,
curr -> curr == null || curr == PENDING ? CANCELED : curr);
if (current == null || current == PENDING) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Please carefully review the updated state machine and existing tests that we have. If you see a use-case not covered by the tests, will appreciate new ideas.

Copy link
Contributor

@bryce-anderson bryce-anderson left a comment

Choose a reason for hiding this comment

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

Looks good but it's complex code so I'd recommend getting one more review before merging.

Copy link
Member

@Scottmitch Scottmitch left a comment

Choose a reason for hiding this comment

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

lgtm after ignored test is brought back to working

@idelpivnitskiy idelpivnitskiy merged commit f345761 into apple:main Aug 14, 2024
11 checks passed
@idelpivnitskiy idelpivnitskiy deleted the split-fix branch August 14, 2024 15:43
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.

3 participants