Skip to content

Query subscriptions can outlive a qu or disconnect that races an in-flight qs or poll #755

Description

@alecgibson

Found while fixing #737. Two teardown races leave a server-side query subscription running after the client has dropped it.

1. qu during an in-flight qs

Agent._queryUnsubscribe only destroys an emitter that's already in agent.subscribedQueries. A qs only registers its emitter after the 'query' middleware and the pub/sub subscribe have finished, and on reconnect also after the known-results reads (#737). A qu that arrives during that window finds nothing to destroy. The emitter is registered anyway and keeps polling and sending queryUpdates until the client disconnects.

  1. var query = connection.createSubscribeQuery('dogs', {})
  2. query.destroy() straight away
  3. agent.subscribedQueries still holds the query.

2. Destroying a QueryEmitter mid-poll doesn't stop it

QueryEmitter.destroy() clears the poll timers, but a poll that's already in flight still ends in _finishPoll → _flushPoll, which schedules a fresh interval poll. Nothing ever clears that timer. With pollDebounce: 0 and pollInterval > 0, the emitter keeps polling the database forever after a qu, or after Agent._cleanup on disconnect. Clients can choose both values (#734).

  1. var query = connection.createSubscribeQuery('dogs', {}, {pollDebounce: 0, pollInterval: 10})
  2. While a db.queryPoll call is outstanding, call query.destroy() and connection.close()
  3. db.queryPoll keeps being called every ~10ms, indefinitely.

Possible fixes

  • Make QueryEmitter.destroy() final: set a flag that _flushPoll checks.
  • Track in-flight qs requests per query id, so a qu or a disconnect can cancel them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions