That gives us enough guarantees that we can simplify the error-handling
code.
We also ensure that the "new connection" handler in livedata_server runs
in a Fiber, which fixes a bug introduced in d049bf7506 where connections
from pre-pre1 clients would crash (due to Meteor.setTimeout which only
works in a Fiber).
If we want the *internal* state of the oplog driver to be consistent, we
need to make sure that we start our observes at a consistent point in
the oplog. (ie, initial inserts need to have been fully processed, so
that we don't process them during the original QUERYING phase, which can
give us a different unpublished buffer.)
Note that only the white-box tests (looked at _unpublishedBuffer, eg)
appeared to be flaky: the actual docs published seemed to be correct in
all cases.
Specifically, this ensures that with sort specifier {'a.x': 1, 'a.y': 1},
{a: [{x: 0, y: 4}]} sorts before {a: [{x: 0, y: 5}, {x: 1, y: 3}]} by
ensuring that the latter only has sort keys [0,5] and [1,3], and not
[0,3].
It does this by ensuring that the different fields used to generate a
sort key are only matched up if they use the same "path" (series of
array indices used during lookup). This is a little stronger than what
MongoDB does: MongoDB lets you do {'a.x': 1, 'a.y.z': 1} where 'a' and
'a.y' are both arrays, and our new rule requires all fields to have
either the exact same set of arrays or to use no arrays at all.
(MongoDB does still have some constraints; eg, with sort key {a: 1,
b:1}, a and b cannot both be arrays. Basically, there may be at most
one "outermost" array across all the fields; and so on recursively, sort
of.
The previously failing test passes now.
This rewrites the sorter to generate "keys" for each doc and find the
lexicographically minimum "key", rather than to look at each sort key
field separately.
This commit doesn't actually change the semantics (and the failing test
still fails) because the key generator actually still computes the full
cartesian product of all keys, rather than only using fields that are
next to each other in arrays.
This 'x' thing is a bit of a hack. The idea is that there are two
consumers of arrayIndices. One is '$', which only looks at the first
index. The other is (soon) sort ken generators, which cares if indices
are explicit or implicit, but doesn't really need to "parse"
arrayIndices; it just will use them to associate branches from different
lookup functions with the matching arrayIndices. 'x' is a simple way to
accomplish this, though I could have made the values of arrayIndices be
objects too.