Repository navigation
Conversation
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
XuPeng-SH
left a comment
There was a problem hiding this comment.
GPT-6 High force review at exact head 3551641.\n\n[P2] Repeated multi-update spills retain each one-shot S3 writer and its sinker buffers until operator reset. sortAndSyncOneTable appends every writer to ownedWriters (pkg/sql/colexec/multi_update/s3writer_delegate.go:683); meanwhile cleanDeleteBatches releases the delegate throttler grant after each spill (lines 269-285). The accumulated writers are only closed by reset/free (lines 901-915, 963-1004), so subsequent spill cycles can retain completed writers’ freelists/arenas after their memory is no longer charged to the throttler. Keep the transaction cleanup ownership lightweight (e.g. retain persisted-object cleanup records separately) and release a successfully synced one-shot writer’s buffers promptly; add a multi-spill test that checks retained memory/bounds.\n\nReview scope note: I traced the changed ownership handoff and relevant cleanup paths, but did not run new tests; full async sink/I/O termination and all real multi-CN cancel/teardown combinations were not independently closed in this review. At review time UT, SCA, coverage and multi-CN BVT checks were still in progress. This is a self-authored PR, so this is a COMMENT rather than an approval/request-changes decision.
|
mo-bot work · Commit: Frozen conflict status contradicts the supplied revision pair. Refresh conflict evidence before authorizing repair or rebase. Earlier review concerns have corresponding source corrections and published measurement evidence. |
|
mo-bot work · Commit: No source repair or rebase is justified, but no-op acceptance remains blocked by unverified mandatory validation and concrete local prerequisite gaps. Supply matching validation diagnostics or provision the recorded prerequisites, then execute the retained validation plan and separate final gate. |
|
mo-bot work · Commit: The validation-only plan remains technically sound, with no source repair or rebase justified. No-op acceptance is withheld until required product validation is verified. The previous validation_complete=true flag was scoped too narrowly to design assessment and is corrected here. |
|
mo-bot work · Commit: No new source repair is demonstrated. The stale conflict atom is removed, but required validation diagnostics remain unverified. Supply matching evidence or execute the retained validation plan before another acceptance gate. |
|
mo-bot work · Commit: Unchanged candidate and evidence retain the prior validation blocker. Supply matching terminal diagnostics or execute the retained validation plan; another unchanged triage/design cycle cannot satisfy acceptance. |
|
mo-bot work · Commit: Review in progress. |
|
mo-bot work · Commit: Review in progress. |
|
mo-bot work · Commit: Review in progress. |
aptend
left a comment
There was a problem hiding this comment.
Deep re-review of exact head 203331f79f72a62e41a52da87c7a6a2561c65bb1, declared base fa7cc1d9b38e3324572a4efc5617033522de0cbf, actual merge-base b09f2c6fc54eb159f549f69db2636fd5fb6e5125.
My previous finding in review 5333838958 is closed. The required total-retained-state and paired-spill evidence is now supplied. I am requesting changes for one independently reproduced test-integration failure, not another claimed S3 runtime defect or a documentation-approval issue.
[P2] Reconcile the remaining frontend restoration tests with the new derived execution context
Location: pkg/vm/process/process2.go:241–242; affected consumers/oracles: pkg/frontend/compiler_context.go:397–402, pkg/frontend/view_schema_provider.go, and pkg/frontend/view_schema_context_test.go:171,348.
doPrepareForRunningWithoutPipeline now puts a private cleanup-budget wrapper in proc.Ctx, so the new view-binding child's execution context is no longer the same object as its compiler/request context. Subscription catalog resolution calls SetContext and then restores the compiler context; that setter assigns the restored request context to proc.Ctx. Consequently, the existing restoration tests compare the original budget-bearing wrapper with its parent request context and deterministically fail require.Same.
The PR correctly updates the initial identity assertion in process/view_binding_process_test.go to semantic tenant/deadline/cancellation/isolation assertions, but leaves the two frontend restoration families on the incompatible pointer-identity oracle.
Actual unchanged-test reproduction on this exact head, with independently built native artifacts:
.agents/skills/mo-dev/scripts/mo-cgo-test -v -count=1 -timeout=120s \
-run '^TestViewSchemaSubscription(DatabaseLookupRestoresContext|SourceResolveUsesPublisherAccount)$' \
./pkg/frontendBoth executions exit 1: 19 failing subscription subcases, 8 passing ordinary/control subcases. Failures include current/historical catalog lookup, success/error/cancellation, ID/index resolution and subscriber-shadow controls. Expected context includes process.cleanupBudgetKey; actual context is its request-context parent. The same assertion failures appear in the exact-head Ubuntu UT job, and required CI is failing.
This is a real deterministic integration/validation failure that prevents the normal test suite from passing; I am not inferring an incorrect publisher read, data loss, security regression or S3 leak solely from context pointer inequality. Please reconcile both test owners with the intended derived-context/restoration contract—retain the existing physical-account, snapshot, cancellation and parent-isolation oracles, and use meaningful context-state assertions if exact pointer identity is no longer required. If restoring the original execution wrapper is required, preserve it in the restoration path instead. Do not simply remove these cases.
Historical closure and current change map
I read all 16 prior reviews, conversation/author replies, all 12 inline comments and every thread (all still administratively unresolved). My prior head d8352ec was rebased, so I used range-diff rather than pretending it is a current ancestor. I inspected the current production ownership/protocol/teardown diff, final map/cleanup simplification, both benchmark harnesses, and the new 203331f integration tests; the unchanged reviewed test contracts were reconciled with that range map.
| Contract | Current technical disposition |
|---|---|
| Writer/spill/clone/transfer → workspace | Lightweight names survive pre-registration failures; accepted objects leave unpublished ownership; failed writers detach buffers. |
| Receive → per-batch ownership receipt → worker release | Retention precedes forwarding/ACK; contiguous marked receipts, not cumulative credits, prove takeover. Protocol field 19 stays independent; receipts use field 20. |
| Rollback/remote finalization → CN retry | Debt survives workspace/stream retirement; fresh retry contexts and original SQL error identities are retained. |
| Partitioned writes | Writer placement remains on the coordinator; remote sources are grouped before wrapping. The old missing-wrapper concern is not reopened. |
| Admission / retry / metrics | Pre-Sync ticket admission, confirmed Delete-batch progress, failed-task rotation and immediate successful draining remain present. |
| View-process/main integration | New derived context conflicts with the remaining frontend restoration oracles: the P2 above. |
The approved live-CN and stop-the-cluster upgrade boundary is respected. Process-crash durability, historical-object sweeping, arbitrary mixed-version write availability and unconditional storage deletion deadlines are not newly demanded. The optional double-decode optimization remains deferred.
Independent validation
- Fresh detached-worktree
make -j2 cgosucceeded; repository native-test wrapper used on Linux/amd64, Go 1.27.1 (Sonic reports its encoding/json fallback). - Focused normal tests passed in 11 affected packages; the initial table_clone filter selected zero cases and is not counted, so its full package was subsequently run and passed. Full metrics package also passed.
- Focused
-race -count=10tests passed for admission concurrency, enqueue/Close, shared cleanup-budget/prepared reuse, pipeline cleanup provenance, receive-before-ACK, ownership receipts, actual MultiUpdate failed cleanup and rollback-after-workspace-removal. Inline ACK ingress was separately run with-race -count=10and passed; the earlier nonmatching CN filter is not counted. - Current-head capacity benchmark, all four shapes at 65,536 tickets,
-benchtime=1x -count=1: 505.1 / 159.0 / 713.1 / 367.0 retained B/ticket for 42/256-byte names and 1/64 objects per task. It includes post-baseline names and production detached callback/queue state and verifies zero tickets after drain. These independently agree with the published capacity evidence. - Paired repeated-spill harness SHA256 matches the published
8df413b4…ed3c9e1; it performs four real Write/Sync/metadata/accept/reset cycles, not a ledger-only microbenchmark. The prior measured paired results are reused with their stated workload/revision limits, not presented as a new current-head paired timing run or proof of zero overhead. - Changed-Go gofmt and range diff-check pass. Exact-head multi-CN pessimistic/proxy BVT jobs pass; UT/coverage/required CI do not. No fresh local multi-CN SQL deployment is claimed.
Scoped unhappy-path audit
| Q | Terminal ownership / wait / growth closure | Result |
|---|---|---|
| Q1 | Writer → workspace or lightweight retry record → CN queue → confirmed Delete/acceptance; partial confirmed batches retire only their tickets | Rechecked source and failure/accepted controls; no additional demonstrated lost-owner or double-cleanup defect. |
| Q2 | Shared teardown budget; independent retry attempt; inline valid ACK state update; worker join before dependency teardown | Focused race/cleanup tests pass. Bounds continue to require context-aware FileService operations; failed top-level Close remains one-shot as documented. |
| Q3 | 65,536 names of at most 256 bytes admitted before Sync; release of heavy buffers; bounded debt measured including owners/queue | Prior performance/capacity gate is closed. Admission can deliberately reject affected new writes during sustained cleanup debt; 128 MiB planning allowance is not an RSS guarantee. |
The remaining blocker is the reproducible frontend test-integration failure above. I found no additional demonstrated blocker in the traced live-CN ownership paths.
What type of PR is this?
Which issue(s) this PR fixes:
Fixes #29257.
What this PR does / why we need it:
CN S3 objects can be persisted before their names reach a transaction workspace. This PR retains cleanup ownership through local writers, Insert, MultiUpdate, remote DELETE, transaction dumps and transfers, tombstone transfer, clone, rollback, and CN teardown. Remote workers release ownership only after an ACK-capable coordinator has retained the names and issued contiguous ownership receipts.
Sync; capacity exhaustion rejects the new write before upload. The receiving CN reserves its ticket before a remote ownership receipt. Confirmed workspace acceptance or successful/absent-object deletion releases the ticket. An ambiguousSyncor Delete retains it.MultiUpdatewriters now stay on the coordinator becausePartitionMultiUpdatehas no remote instruction codec. Remote source scopes are grouped by CN before moving the writer; this preserves shuffle receiver ownership and writer parallelism without changing the wire protocol.Goals and engineering principles
Maximize useful cleanup coverage at small, measured normal-path cost and proportionate implementation complexity; do not pursue unconditional elimination of every orphan object.
Current implementation and upgrade contract
Rebased onto
main@37ba0712974d4a1ebe3fe8cd8e6a4daba7400f5e; current head4cf6f8689c0e84f2b66609cf2bcc58cccce9c73d.MultiUpdate.Free→ workspace callback → repeated failure/recovery path. Remove the redundant remote-DELETE file-service field.protocol_versionremains field 19, and the ownership receipt uses field 20. Independently encoded wire bytes verify that one cannot be mistaken for the other. Fresh generated output compares byte-for-byte with the checked-in binding.The final correction commit is production −46 lines, documentation −193, tests/benchmarks +237 (net −2). The full PR still adds the ownership/admission/retry mechanism; this is not a claim that its overall diff is small. Each added benchmark addresses a previously missing proof, rather than increasing test count for its own sake.
Validation
Local validation applies to the final source tree; the commit itself made no source changes after testing. macOS arm64 / Apple M4 / Go 1.26.4, each worktree's own source-stamped native build.
-race -count=1tests passed for all 13 changed packages:cnservice,objectio/ioutil,pb/pipeline,sql/colexec,deletion,insert,multi_update,table_clone,sql/compile,util/metric/v2,disttae,vm/pipeline,vm/process.gofmt,git diff --check,go vetand repository-pinnedgolangci-lintpassed (0 issues).molintproduced the same 12 recover diagnostics as the clean main baseline, with no new diagnostic. Native andmo-servicebuilds passed.Full retained cleanup state at capacity
BenchmarkUnpublishedS3RetainedCapacityallocates all names after the baseline and uses production receive → real transaction-detached callback → CN retry queue paths at 65,536 names. Post-GC live bytes include admission, names, owners, callback storage, queue/timestamps and FS references. Shared FS caches, S3 payloads and unrelated in-flight queries are excluded. Every sample then drains and verifies zero remaining tickets.Final medians:
-benchtime=3x -count=5; pre-consolidation source is rebasedd42fca1d37with the identical capacity harness,-benchtime=1x -count=3. Capacity is fixed per iteration, not throughput-scaled. The 1-object/task cases retain 38–42% less live memory after consolidation.Operational sizing must exceed retained live bytes: 128 MiB/CN is an initial bookkeeping-only planning allowance for these measured shapes (~2.9× the largest measured live set), not an enforced RSS bound or a guarantee for every fallback shell/GC setting. Add ordinary writer buffers, file-service caches and workload memory separately. The 80%-ticket alert is a starting threshold, not proof that every CN has sufficient memory headroom.
Paired repeated-spill cost versus main
The exact same
unpublished_s3_bench_test.go(SHA2568df413b4ef19041040e1b2c2b39ef47ed5b8459dbd1f60b1c251999cded3c9e1) runs on verifiedmain@37ba071297and this PR. Each operation performs four real Write → Sync → metadata → acceptance/reset cycles, each of 1 or 128 MiB logical input. PR admission is enabled; main uses its existing path. Input construction and physical deletion of accepted objects are excluded on both revisions. MemoryFS retains real encoding/compression work but does not model cloud-S3/network latency.One warmup per revision, then 3 ABBA rounds (6 samples/revision), 3 operations/sample,
GOMAXPROCS=4; medians:Allocation-count overhead is 0.11% / 0.27%; bytes are +0.035% / approximately flat. Time ranges overlap (1 MiB: main 5.698–9.438 ms, PR 5.819–6.753; 128 MiB: main 742.795–896.385 ms, PR 743.626–826.469). This supports small measured bookkeeping cost for this workload, not zero overhead, statistical significance or an end-to-end SQL throughput guarantee.
Reproduce capacity on this head:
For the paired run, copy the exact benchmark file unchanged into a disposable worktree at the base above and build native dependencies independently. Build each package's test binary with the CGo wrapper, warm each once, then alternate the binaries in ABBA order three times:
Review dispositions and boundaries
The previous mandatory total-retained-memory / repeated-spill evidence gap is addressed above. The ACK ingress comment now explicitly pins no I/O / no blocking wait. Previous primary-error preservation, valid commit/rollback outcomes, canceled cleanup, buffer retention, queue growth/drain and partition placement findings remain fixed and covered by the current checks. The mixed-version concern is now outside the explicitly agreed stop-upgrade scope. MultiUpdate double-decode optimization remains deferred without profiling; it is not claimed fixed.
Self-review traced ownership, waits and growth across all changed contracts; no remaining demonstrated blocker in the requested live-CN scope. This is not independent approval, and existing reviewers' request-changes states are not dismissed.
Remaining limits are intentional: names are not durable across process crashes; no historical-object sweep is added; context-aware FileService operations are required for deadline bounds; CN shutdown retains dependencies if bounded cleanup fails, and the top-level close remains one-shot. Sustained debt can reject new S3 uploads at the admission cap.