feat: Shared Schema Cache (SchemaStore) — Step 6.1#538
feat: Shared Schema Cache (SchemaStore) — Step 6.1#538tnaum-ms merged 8 commits intofeature/shell-integrationfrom
Conversation
…1 WI-1)
Introduce SchemaStore — a shared, cluster-scoped schema cache that
accumulates schema data per {clusterId, databaseName, collectionName}.
Key features:
- Lazy singleton with Map<key, SchemaAnalyzer>
- Debounced onDidChangeSchema event (1s per key)
- clearSchema fires immediately (not debounced)
- clearCluster removes all schemas for a cluster
- Implements vscode.Disposable
21 unit tests covering read/write ops, key isolation, event
debouncing, and lifecycle management.
Remove _schemaAnalyzer and _highestPageAccumulated from ClusterSession. Schema operations now delegate to the shared SchemaStore singleton: - addDocuments → SchemaStore.addDocuments() - getKnownFields → SchemaStore.getKnownFields() - getPropertyNamesAtLevel → SchemaStore.getPropertyNamesAtLevel() - Remove unused getCurrentSchema() method ClusterSession stores _clusterId, _databaseName, _collectionName for SchemaStore key construction. Register SchemaStore as a VS Code disposable in extension.ts. Drop page-based dedup (_highestPageAccumulated) — schema accumulates monotonically and statistics are already documented as approximate.
Extend ExecutionResult with optional source.namespace extracted from @MongoSH's ShellResult.source. This preserves the database/collection name that was previously discarded. executeScratchpadCode now feeds document results to SchemaStore using a very conservative approach: only 'Cursor' and 'Document' result types are fed. All other types (InsertOneResult, UpdateResult, etc.) are skipped. This enables cross-surface schema sharing — running db.users.find() in the scratchpad populates field completions for the users collection across all Collection View tabs.
Wire SchemaStore cleanup into existing lifecycle hooks: - removeConnection: clearCluster() alongside CredentialCache cleanup - deleteCollection: clearSchema() for the dropped collection - deleteDatabase: clearDatabase() for all collections in the database - ClustersClient.deleteClient: clearCluster() on client teardown Add clearDatabase() method to SchemaStore for database-scoped cleanup. Add unit test for clearDatabase().
There was a problem hiding this comment.
Pull request overview
Introduces a shared, extension-wide schema cache (SchemaStore) keyed by {clusterId, databaseName, collectionName} to enable cross-tab and scratchpad-driven schema sharing, and wires lifecycle cleanup into disconnect/drop flows.
Changes:
- Added
SchemaStoresingleton with per-collection schema accumulation, debounced change events, and clear/reset APIs. - Refactored
ClusterSessionto feed/query schema viaSchemaStoreinstead of per-session accumulation. - Extended scratchpad execution results with
source.namespaceand feeds document results intoSchemaStore; added schema cleanup hooks on connection/database/collection removal.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/extension.ts | Registers SchemaStore for disposal with extension lifecycle. |
| src/documentdb/SchemaStore.ts | Implements singleton schema cache, debounced change events, and clear/reset APIs. |
| src/documentdb/SchemaStore.test.ts | Adds unit tests for SchemaStore behavior (read/write, isolation, debounce, lifecycle). |
| src/documentdb/ClusterSession.ts | Delegates schema operations to SchemaStore and feeds query results into shared cache. |
| src/documentdb/ClustersClient.ts | Clears SchemaStore data when a client is deleted. |
| src/documentdb/scratchpad/types.ts | Extends ExecutionResult with optional source.namespace metadata. |
| src/documentdb/scratchpad/ScratchpadEvaluator.ts | Extracts source.namespace from @mongosh shell results. |
| src/commands/scratchpad/executeScratchpadCode.ts | Feeds scratchpad document/cursor results into SchemaStore. |
| src/commands/removeConnection/removeConnection.ts | Clears cluster schema cache on connection removal. |
| src/commands/deleteDatabase/deleteDatabase.ts | Clears database schema cache on database deletion. |
| src/commands/deleteCollection/deleteCollection.ts | Clears collection schema cache on collection deletion. |
No circular dependency exists between ClustersClient and SchemaStore. Replace dynamic import() with a normal static import. Addresses PR review finding #5.
|
Re: lazy import in deleteClient — Fixed in 700a4fd. Replaced the lazy |
PR Review ResponsesFinding 1 (live cross-tab updates): Acknowledged. Severity assessed as Low. The shared Finding 2 (silent invalidation): Acknowledged. Severity assessed as Low. Finding 3 ( Finding 4 ( Finding 5 (lazy import): Fixed in 700a4fd — replaced with static import. |
Add '_id' in d to the type predicate in feedResultToSchemaStore so the
narrowing to WithId<Document> is sound. Documents from projections
with { _id: 0 } are now correctly excluded — their artificial shapes
should not feed schema analysis.
Addresses PR review finding #3.
|
Re: unsound type predicate — Fixed in d756cb6. Added |
Step 6.1: Shared Schema Cache (
SchemaStore)Introduces a
SchemaStoresingleton that accumulates schema data per{clusterId, databaseName, collectionName}, enabling cross-tab and scratchpad schema sharing.What Changed
New:
SchemaStoresingleton (src/documentdb/SchemaStore.ts)Map<"clusterId::db::coll", SchemaAnalyzer>— shared schema cacheonDidChangeSchemaevent (1s per key) to avoid excessive consumer churnclearSchema()/clearCluster()/clearDatabase()for lifecycle cleanupDisposableinextension.tsRefactored:
ClusterSessiondelegates toSchemaStore_schemaAnalyzerand_highestPageAccumulatedfieldsgetKnownFields()andgetCurrentPageAsTable()now delegate toSchemaStoregetCurrentSchema()method_clusterId,_databaseName,_collectionNamefor SchemaStore key constructionNew: Scratchpad results feed
SchemaStoreExecutionResultwithsource.namespace(extracted from@mongoshShellResult.source)executeScratchpadCode.tsfeeds document results (very conservative: onlyCursorandDocumenttypes)db.users.find()in the scratchpad now populates field completions for theuserscollection across all Collection View tabsWired: Schema cleanup on disconnect/drop
removeConnection→clearCluster()deleteCollection→clearSchema()deleteDatabase→clearDatabase()ClustersClient.deleteClient→clearCluster()(lazy import to avoid circular dep)Tests
Key Behaviors
find()resultclearCluster()clearSchema()Plan
Full design doc with architecture, decisions (D1–D7), resolved questions (Q1–Q3), deviations log: docs/plan/06.1-shared-schema-cache.md (gitignored, local only)