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

IntroToRx recommends wrong Window overload #2130

Open
idg10 opened this issue Jun 17, 2024 · 0 comments
Open

IntroToRx recommends wrong Window overload #2130

idg10 opened this issue Jun 17, 2024 · 0 comments

Comments

@idg10
Copy link
Collaborator

idg10 commented Jun 17, 2024

The Window section of the Partitioning page has this example:

public static IObservable<IObservable<T>> MyWindow<T>(
    this IObservable<T> source, 
    int count)
{
    IObservable<T> shared = source.Publish().RefCount();
    IObservable<int> windowEdge = shared
        .Select((i, idx) => idx % count)
        .Where(mod => mod == 0)
        .Publish()
        .RefCount();
    return shared.Window(windowEdge, _ => windowEdge);
}

That final expression is problematic:

shared.Window(windowEdge, _ => windowEdge)

This effectively tries to use the same sequence for both openings and closings.

People might reasonably expect this to produce contiguous windows, in which there are neither gaps nor overlaps. It's reasonable to think that if the same source is specifying both the starts and ends of each window, that each new window would start exactly where the previous one ends, with the effect that every item would go into exactly one window.

This is not in fact the case, because that openings/closings overload of Window ends up making multiple subscriptions to the same source: once in its role as the openings observable, and then once per window for the closings.

In general in Rx, multiple subscriptions to the same source do not have to produce the same events. The situation where this does happen is a special case that we describe as a 'hot source'. This is an informal term, and not something Rx actually recognizes—we talk about 'hot sources' to describe a form of behaviour, but System.Reactive has no way of detecting when something is acting as a hot source.

(In principle, it could recognize the use of things like Publish, Multicast, or Subject to detect when there logically really is a single event flowing through multiple paths. But this would require the addition of tracking of a kind Rx has never previously performed. And even if we did this, it would be too easy for the application to add a layer that made it impossible for Rx to detect this, leading to inconsistent behaviour depending on whether non-System.Reactive implementations are added to the mix. Currently System.Reactive optimizes certain cases where it detects our own operators are in use adjacently, but we aim never to change behaviour just because you've put something else in the mix.)

The IntroToRx example should be changed here. Since the example (which was brought over from the 1st edition) was apparently selected to motivate the the use of this particular form of Window, we might need to rewrite this bit entirely.

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

No branches or pull requests

1 participant