Skip to content

Connection state recovery uses (nearly) unindexable query yielding a (near) full collection scan #17

@genisd

Description

@genisd

The query used for connection recovery (restoreSession()) uses a query which is not efficiently indexable.

Specifically, say one has an index on data.opts.rooms, the where clause cannot be looked up from that index.

        {
          $or: [
            {
              "data.opts.rooms": {
                $size: 0,
              },
            },
            {
              "data.opts.rooms": {
                $in: session.rooms,
              },
            },
          ],
        },

data.ops.rooms size == 0 cannot be looked up from an index 😞, mongodb by default will do a full index scan over _id index (which essentially is a full collection scan). I tried not exists as an alternative, but that didn't improve it either (tested on mongodb 6).

The comment on line 830 is not accurate, one cannot create a composite index containing two arrays (data.opts.rooms && data.ops.except). And even if one could, the index does not appear to be usable for the data.opts.rooms size == 0.

My understanding is that the rooms field is only populated on like "roomless" global broadcasts.

So I'm wondering how we could improve this implementation.
We ourselves don't use room less broadcasts, so we removed the OR data.ops.rooms size == 0 clause for us.

I'm wondering what the best solution would be to improve this here.

I was thinking that perhaps instead of not setting a room for a global broadcast we could instead use a reserved magic string/room like GLOBAL_BROADCAST for global broadcasts. That way we can remove the OR clause and by default include the GLOBAL_BROADCAST magic string in the room and the except filter.
With that approach an index on data.opts.rooms will perfectly reduce the candidate documents to be replayed.

Would that be feasible? I'm hoping for feedback and/or better ideas for this.

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