Phase 1 cache rewrite — long-lived design and execution plan - #967
Open
AnthonyMDev wants to merge 26 commits into
Open
Phase 1 cache rewrite — long-lived design and execution plan#967AnthonyMDev wants to merge 26 commits into
AnthonyMDev wants to merge 26 commits into
Conversation
Adds the engineering plan and manager-facing summary for Phase 1 of the cache rewrite (3.0). Phase 1 scope is foundations (SQLite restructure + field-aware Record) and TTL via @CacheControl; Phase 2 features (@onDelete, eviction, ChainedNormalizedCache) are deferred. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the workflow document that an AI agent (Claude Code) follows when executing the Phase 1 cache rewrite. Defines branch and PR conventions, per-PR loop, quality gates, escalation triggers, the 31 stacked PRs that make up Phase 1, and session-bootstrap steps for resuming work across sessions. Companion to the engineering design plan (apollo-ios/Design/cache-rewrite-phase1-plan.md); the engineering plan specifies what to build, this document specifies how to ship it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
✅ Docs preview has no changesThe preview was not built because there were no changes. Build ID: 4c7c53c810f7a990ec254e95 ✅ AI Style Review — No Changes DetectedNo MDX files were changed in this pull request. Review Log: View detailed log
|
✅ Deploy Preview for apollo-ios-docc canceled.
|
Update execution plan §3, §7, §8, and §10 so that `cache-rewrite/phase-1-plan` is the long-lived base for the entire 31-PR stack. PR-001 bases on the plan branch (not main); subsequent PRs stack as before. The plan branch itself is only merged into main after every PR in the stack has merged into it. Plan revisions can land directly on the plan branch and propagate down through every open stacked PR via rebase. The 3.0-alpha and 3.0-beta release tags are cut from the plan branch; 3.0 final is cut from main after the plan branch merges. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a fourth Phase 1 design doc — cache-rewrite-phase1-perf.md — specifying the performance measurement methodology and the published comparison dataset that will accompany the 3.0-alpha tag. Covers four measurement tiers (end-to-end ApolloClient.fetch, NormalizedCache protocol level, raw SQLite, memory/CPU profiling) across synthetic, real-schema, and stress workloads. Methodology mirrors Zach's existing benchmark (50 iterations, mean/std-dev/P50/P95/P99, multi-device) so SQLite numbers can compare directly against the published Confluence baseline. Adds three new PRs to the execution plan: - PR-004a (Phase 0): capture 2.x performance baseline dataset - PR-011a (Phase 1A): comprehensive measurement harness for Tier 1+2 - PR-011b (Phase 1A): alpha-vs-2.x comparison reporter Updates Phase 1A exit criteria so the 3.0-alpha tag is gated not only on SQLite gates green, but also on no `regressed` verdict in the published dataset (or all such regressions explicitly accepted). Timeline impact: - Phase 0: 2 wk -> 3 wk (engineer + calendar) - Phase 1A: 4 wk -> 5 wk effort; 6-7 -> 7-8 calendar - Total Phase 1: 17 -> 19 engineer-weeks; 21-24 -> 23-26 calendar; with 25% contingency 27-30 -> 29-33 (~6.5-7.5 months) Companion plan, summary, and execution docs updated with cross-refs. PR count goes 31 -> 34. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update execution plan §2 and §7 to remove the blanket "max 2 stacked unmerged PRs" cap and replace it with a PR-type-aware policy: - ADR PRs (Phase 0 docs) merge into cache-rewrite/phase-1-plan as they are approved. One or two sit in active review at any time. - Code PRs (Phase 1A through 1D) stay open as a long-running stack with no preset cap; the reviewer batches them at end-of-phase or as convenient. The agent pauses only on explicit reviewer instruction, §6 escalation triggers, or genuine state dependencies between in-flight PRs. The agent does not unilaterally merge any PR — merges remain reviewer- initiated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apollo iOS 3.0 ships the Phase 1 cache rewrite as a coordinated breaking release: SQLite schema change, public Record API change, generated code shape change, and TTL evaluation behavior. Captures four rejected alternatives (2.x feature flag, staged minor releases, parallel cache module, hold-for-Phase-2) and the positive/negative consequences. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ld) (#969) Record.fields changes type from [CacheKey: any Hashable & Sendable] to [CacheKey: CachedField], where CachedField carries the field's value alongside its writtenAt epoch timestamp. The record[key] subscript stays backward-compatible (returns Value? by unwrapping .value), so the executor and most consumers don't change. The breaking surface is restricted to code that iterates record.fields directly. Captures three rejected alternatives (parallel side-channel, lazy proxy) and the positive/negative/neutral consequences — including the Hashable/Equatable semantics change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…, read-mode split) (#970) Three interlocking decisions defining the runtime behavior of @CacheControl: tri-state maxAge (nil / 0 / N>0; bare @CacheControl is a codegen error); selection-set-scoped TTL (any expired field in the current query → whole-query miss; fields outside the selection ignored); strict-vs-permissive read-mode split on ApolloStore.load (strict enforces TTL on consumer-initiated reads, permissive bypasses TTL only — not genuine missing-value errors — for watcher re-reads on didChangeKeys). Captures six rejected alternatives across the three sub-decisions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ming) Updates ADR 0003, engineering plan, and execution plan ahead of ADR 0005 (PR-004b) which will document the consumer-facing stale-tolerance API: - RequestConfiguration.ttlEnforcement: TTLEnforcement = .strict - Source.cache(containsStaleFields: Bool) — staleness signal as associated value on the cache source case (structurally inapplicable to network responses) - JSONDecodingError.MissingValueReason — diagnostic distinction between absent and expired - .revalidateCache case on CachePolicy.Query.CacheAndNetwork — built-in SWR pattern; always reads permissively as part of its semantics ADR 0003 §2.3 read-mode table and §2.4 pseudocode updated to reflect that permissive mode marks staleness on the response (rather than silently returning) and that the throwing path uses MissingValueReason. Engineering plan §4.2 pseudocode updated to match. §6.4 documents the Source enum shape change and the GraphQLDependencyTracker extension to compute both earliestExpiry and the staleness flag. Execution plan §8 Phase 1C: adds PR-022a for the stale-tolerance API surface (~450 LoC); expands PR-022 and PR-024 to cover staleness tracking. Phase 1C goes from 7 PRs to 8 PRs; total stack 34 → 36. The intersection .revalidateCache + ttlEnforcement = .strict is documented as redundant with .cacheFirst + ttlEnforcement = .strict (accepted small cost of a composable two-axis design). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e propagating reads) (#971) Merging ADR 0004 (Watcher × TTL: opt-in auto-refresh, permissive propagating reads) into the plan branch per the ADR-merge-as-approved policy. Approved post-meeting.
Merging ADR 0005 (Stale-tolerance API surface — RequestConfiguration.ttlEnforcement, Source.cache(containsStaleFields:), MissingValueReason, .revalidateCache) into the plan branch. Revised post-review to clarify .revalidateCache honors ttlEnforcement on the internal read (resolving the orthogonality inconsistency with Alternative F). Approved post-meeting.
Approved by Anthony — codifies the inline-documentation conventions established during PR-005 review.
…997) Approved as part of the manager-tracker workflow setup. The single failing unit test on the docs-only branch is unrelated — pre-existing flaky test (`test__cancellingTask__propogatesTaskCancellationToInterceptors`).
…lan (#991) Approved — companion to the PR-006 stack discussion. Documents the Phase 1A interim writtenAt default and the Phase 1C migration trigger.
…004a) (#980) PR-004a — macOS 2.x cache baseline benchmark harness + dataset. All CI green. Approved.
#999) PR-007 — schema_metadata table + version read/write. Foundation for PR-008/010 migration logic.
… (PR-008) (#1000) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 28, 2026
…g design, 009g-bis) (#1014) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-plan # Conflicts: # Tuist/ProjectDescriptionHelpers/Targets/Target+ApolloPerformanceTests.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1 Cache Rewrite — Long-lived plan branch
This is the long-lived feature branch that holds the four Phase 1 design docs (summary, plan, execution, perf) and accumulates every implementation PR as it merges. Not merged into
mainuntil all PRs in the stack have merged into it — see execution plan §10 done conditions. Each implementation PR's diff is reviewed independently and merges into this branch, not intomaindirectly.Progress Tracker
Last updated: 2026-05-29 · In-plan PRs merged: 11 / 37 (≈ 30%) · Active phase: 1A · Latest activity: PR-008b merged (#1005) — position-keyed records DDL with
(cache_key, field_name, position)PK; schema version stays at v3 (aligned with Apollo iOS 3.x); doc references to v4 corrected in the same PR. ADR 0007 (#1003) also merged — selection-set-aware cache reads.Status legend
cache-rewrite/phase-1-planPhase 0 — Design lock, ADRs, performance baseline ✅
Five Architecture Decision Records establishing the design contract, plus a 2.x performance baseline used as the reference dataset for the eventual 3.0-alpha comparison.
CachedField)Phase 0: 6 of 6 merged. Phase complete.
Phase 1A — SQLite schema rewrite + field-aware
Record(11 PRs)End state: 3.0-alpha tag with new SQLite row-per-field schema and field-aware
Recordshipping. Performance gates green; comparison dataset published.CachedFieldtype (no consumers yet)Record.fieldstype to[CacheKey: CachedField]schema_metadatatable + version detectionSchemaVersion+SQLiteSchemanamespaceSQLiteNormalizedCacheto new schema; drop-and-rebuild migrationPhase 1A: 5 of 11 merged. Next up: PR-009 (row-per-element CRUD against the position-keyed schema). Note: the ADR 0007 sub-phase 1A.5 (PRs PR-009a–h for selection-set-aware field projection) is approved as a design but not yet reflected in §8 — pending a follow-up restructure PR after PR-009 lands.
Phase 1B —
@cacheControlcodegen end-to-end (7 PRs)End state: codegen emits
cacheControl:metadata onSelection.Field. Runtime stores but does not yet enforce TTL — landed in Phase 1C.@cacheControldirective definitions (JS frontend)cacheControlMaxAgethroughCompilationResultSelection.CacheControlDirectiveruntime typeIR.FieldexposescacheControlMaxAgeSelectionSetTemplateemitscacheControl:parameterTestCodeGenConfigurations; snapshot testsPhase 1B: 0 of 7 merged. Blocked on Phase 1A.
Phase 1C — TTL evaluation, read-mode split, stale-tolerance API (8 PRs)
End state: TTL is enforced on strict reads; permissive reads mark staleness; watcher uses permissive reads;
.revalidateCachecache policy ships.TimeProviderprotocol +ApolloStoreintegrationTTLEnforcementenum +ApolloStore.load(_:ttlEnforcement:)CacheDataExecutionSource.resolveFieldRequestConfiguration.ttlEnforcement,Source.cache(containsStaleFields:),MissingValueReason,.revalidateCache)GraphQLResultNormalizerinjectswrittenAton cache writesGraphQLDependencyTrackercomputesearliestExpiry+containsStaleFields.permissiveondidChangeKeysre-readTTLTests.swiftcovering all 9 sample scenarios + boundary casesPhase 1C: 0 of 8 merged. Blocked on Phase 1B.
Phase 1D — Opt-in watcher refresh, hardening, beta (5 PRs)
End state: 3.0-beta tag pushed. Migration guide live. Internal beta cycle complete with zero P0/P1 issues.
GraphQLQueryWatcher.automaticallyRefreshOnExpiryflag + timerInMemoryNormalizedCacheparity for TTLDocumentation.doccfor 3.0@cacheControlusage inTestCodeGenConfigurationsPhase 1D: 0 of 5 merged. Blocked on Phase 1C.
Supporting PRs (governance / docs, not in §8)
These don't ship code in the main stack but capture project-wide decisions (workflow conventions, design clarifications).
position)How this tracker stays current
Per execution plan §4.7, when an implementation PR merges into this branch, the agent updates the corresponding row above: flips 🟡 → ✅, fills in the merge date, and adjusts the per-phase / overall counters. The update is mechanical (
gh api repos/.../pulls/967 -X PATCH -F body=@…) and happens immediately after the rebase of the next stacked PR.Design documents
The plan branch ships four design docs that are the source of truth for the rest of the work:
cache-rewrite-phase1-summary.md— manager-facing summarycache-rewrite-phase1-plan.md— engineering design plancache-rewrite-phase1-execution.md— AI execution plan with PR listcache-rewrite-phase1-perf.md— performance measurement planapollo-ios/Design/adr/