Skip to content

Query subscriptions emit data in an incorrect order #793

@MrSlateZB

Description

@MrSlateZB

When using a Query subscription, I think there is an implicit assumption that the last call to onData will contain the most recent data in the database. Or in other words, if I put 'A', 'B', 'C' into the database, I expect my onData callbacks to receive 'A', 'B', 'C' in that order. Or, at the very least, I expect 'C' to be the last emission I get. Unfortunately, that is not currently always the case.

It seems like this ordering was trying to be enforced at the BoxStore level. In the ObjectClassPublisher a concentrated effort is made to ensure that entity id changes are processed in a synchronized fashion by locking it to one thread at a time. In other words, it ensures that changes are emitted to data observers in the order that they were published.

The problem appears within the QueryPublisher because it takes those changes and publishes them to an unbounded thread pool. Once there, it executes the query to get the data, and emits them to all child observers. This is problematic, because there is nothing preventing multiple threads in the pool from querying and emitting data to the child observer. An example best illustrates the problem.

Lets say we have a Box with a list of car brands. For simplicity, imagine only one thread runs at a time.

  1. Some time in the past, data observer is subscribed to query to get all car brands
  2. InsertThread - Put Toyota into car brand box
  3. ThreadPool-1 - Receives change, queries box, and gets { Toyota } ... Context switch occurs
  4. InsertThread - Put Lexus into car brand box
  5. ThreadPool-2 - Receives changes, queries box, and gets { Toyota, Lexus }. Emits to data observer
  6. ThreadPool-1 - Emits list { Toyota } to data observer

Now, the query data observer incorrectly believes that the box contains only Toyota instead of Toyota and Lexus.

The way we are currently working around this problem is only using the entity class observers. Then in the observer we have a synchronized block that will run find() on our query and emit the data. You might think the synchronized block wouldn't be required, but the initial publishSingle for entity class observers has the possibility of running concurrently with the entity id based change processing.

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions