Skip to content

Switch publishes the removals and the new source's items as two changesets #1150

Description

@dwcullop

Switching to a new source is published as two changesets rather than one: a set of removals for what the previous source contributed, and then whatever the new source publishes when it is subscribed to.

Cache/Internal/Switch.cs, roughly:

using (var scope = queue.AcquireLock())
{
    sourceId = ++activeSourceId;

    if (current.Count != 0)
    {
        scope.EnqueueNext(/* removals for everything the old source contributed */);
        current.Clear();
    }
}

subscription.Disposable = source.SubscribeSafe(...);

The removals are enqueued, and then the subscription to the new source happens. If subscribing causes an immediate publication of the items already in that source, which it normally will, those arrive as a second changeset.

That breaks the general rule of one frame, one changeset. A subscriber sees the collection empty out and then refill, rather than a single changeset carrying the removals and the additions together. Anything binding to the result gets a visible flicker, and anything counting changesets sees two where it should see one.

The same is true of the implementation currently on main, which does destination.Clear() in a Do on the outer sequence before PopulateInto sees anything from the new source, so this is long standing rather than newly introduced.

Raised from review on #1137, where the observation was that the fix belongs in its own change rather than being folded into a completion fix.

The list Switch has the same shape and would want the same treatment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions