diff --git a/PLAN.md b/PLAN.md index 2959b07..081d6c2 100644 --- a/PLAN.md +++ b/PLAN.md @@ -467,7 +467,7 @@ answers, and the trade is only acceptable because the lie is removed first. | M1 | **Cursors + wire polish** | getMore / killCursors / batchSize; server-side cursor state with idle timeout; sessions plumbing (lsid accepted) as drivers send it; hello advertisement updates; **`moreToCome` on requests** (see the bug below); command-monitoring assertions in the spec runner | crud spec suite green; e2e green | | M2 | **The `aggregate` command surface** | `$out` and `$merge` (7 of the 13 failures), and refusing every pipeline construct the engine does not implement instead of answering `0` (amendment A6). The other 6 failures are blocked on M2.5, M4 and M8 — see `docs/M2_DESIGN_REVIEW.md` §7 | `aggregate-*.json`: 0 fail among the 7 reachable cases | | M2.5 | **The aggregation engine** | expression evaluator, per-stage document iterator, the accumulators, `$unwind`; `$lookup`/`$facet` explicitly out of the first cut (amendment A6) | a purpose-built stage corpus, every expectation measured against mongod | -| M3 | **Update operators + index types** | $setOnInsert, $addToSet, $mul, $min/$max, $pop, $pullAll, $currentDate, pipeline updates; partial + hashed indexes | remaining crud coverage; e2e3/e2e4 green | +| M3 | **Update operators + index types** | `distinct` (**done**); then $setOnInsert, $addToSet, $mul, $min/$max, $pop, $pullAll, $currentDate, `arrayFilters`, pipeline updates; partial + hashed indexes | remaining crud coverage; e2e3/e2e4 green | | M4 | **Sessions + transactions** | logical sessions, snapshot isolation on the mmap engine, write concern at commit | sessions + transactions spec suites green | | M5 | **Change streams** | change feed + resume tokens (likely log-seq based), getMore integration | change-streams spec suite green | | M6 | **Admin/ops commands** | dbStats, collStats, serverStatus, ping, buildInfo, listDatabases filters, dropDatabase durability (log it) | mongosh UX smoke; e2e green | @@ -585,6 +585,11 @@ gaps (`bad update`, `update must be a document` — M3), unimplemented commands (`distinct`, `$merge`, `$out` — M2/M3), and result-shape mismatches in `bulkWrite`/`insertMany`. That list, not the total, is the milestone backlog. +All three named commands have since landed: `$out`/`$merge` in M2, `distinct` +as M3's first commit. The backlog the same grouping gives today is +`arrayFilters` (14 cases), the `findOneAndUpdate`/`findOneAndReplace` shapes +(~10), pipeline-form updates (~10), and `create-null-ids` (6). + --- ## 4. Ground rules (inherited and new) @@ -1040,6 +1045,33 @@ has to be its own commit with its own re-recorded scorecard. `$out`/`$merge` durability semantics, whether the expression evaluator is shared with M3's pipeline updates, and whether `allowDiskUse` has to stop being a lie. +- **M3 update operators** — open. `distinct` landed first because it was a + whole missing command with no dependencies, and measuring it turned up three + things worth keeping, none of which are `distinct`'s to fix: + - **An unknown query operator matches nothing instead of erroring.** + `{x: {$bogus: 1}}` answers `ok: 1` with an empty result on `find`, `count` + and `aggregate` alike, where mongod answers `BadValue` (2) "unknown + operator: $bogus" on all three. Measured on both servers side by side. + This is the same class as M2's six silent wrong answers — a typo'd + operator reads as "no matches" — and it lives in the shared query path, so + it is one fix for every command rather than one per command. It predates + `distinct` and is not in its commit for that reason. + - **A non-string collection name is `BadValue` where mongod says + `InvalidNamespace` (73).** Dispatch refuses it while resolving the lock + target, before any handler runs, so this is one answer for the whole + command table. Worth correcting as its own commit, with the codes measured + per command — three `db.aggregate()` cases in the corpus fail on the same + message for an unrelated reason (they name no collection at all, M4). + - **`distinct` is unbounded in memory**, holding every value at the key + before deduping. Joins `$group` and `$sort` in that list; mongod caps the + reply at 16 MB, which is a different and cheaper answer than spilling. + + Left deliberately: `distinct-comment.json`'s "pre 4.4, server error" case + wants a *document*-valued `comment` refused, because this server reports + 4.4.0 and mongod only accepted one from 4.4.14. `estimatedDocumentCount` + already carries the identical standing failure, and emulating a bug fixed in + 4.4.14 for one command would make the two disagree. `distinct-collation` + needs M8 and now fails with the honest "expected 1 elements, got 2". - **M4 transactions**: snapshot isolation over mmap (COW vs undo), read concern snapshot, conflict → TransientTransactionError semantics, retryable-writes interplay.