Dual Storage Architecture#9
Conversation
* Dual writer: mode 3 * Add integration tests for playlits in mode 3 * Remove todo * Update pkg/apiserver/rest/dualwriter_mode3.go Co-authored-by: Arati R. <33031346+suntala@users.noreply.github.com> * Admin: Fixes an issue where user accounts could not be enabled (#88117) Fix: unable to enable user * [REVIEW] FInish mode 3 and add tests * Improve logging * Update dependencies * Update pkg/apiserver/rest/dualwriter_mode3_test.go Co-authored-by: maicon <maiconscosta@gmail.com> * remove test assertion * Use mode log when dual writer is initiated --------- Co-authored-by: Arati R. <33031346+suntala@users.noreply.github.com> Co-authored-by: gonvee <gonvee@qq.com> Co-authored-by: maicon <maiconscosta@gmail.com>
Codoki PR ReviewSummary: Preserve update consistency, fix metrics/log context Issues (Critical & High only)
Showing top 1 issues. Critical: 0, High: 1. See inline suggestions for more. Key Feedback (click to expand)
Confidence: 3/5 — Needs work before merge (1 high · status: Requires changes) Sequence DiagramsequenceDiagram
participant Caller
participant DualWriterMode3
participant Storage
participant Legacy
Caller->>DualWriterMode3: Update(name, objInfo,...)
DualWriterMode3->>Storage: Update(...)
alt storage error
Storage-->>DualWriterMode3: err
DualWriterMode3-->>Caller: error
else success
Storage-->>DualWriterMode3: res, async, nil
DualWriterMode3->>Legacy: Update(..., async)
Legacy-->>DualWriterMode3: (ignored in async)
DualWriterMode3-->>Caller: res, async, nil
end
React with 👍 or 👎 if you found this review useful. |
| } | ||
| return obj, created, err | ||
| startLegacy := time.Now() | ||
| defer cancel() |
There was a problem hiding this comment.
| defer cancel() | |
| ```go | |
| if err != nil { | |
| log.Error(err, "unable to update in storage") | |
| d.recordStorageDuration(true, mode3Str, options.Kind, method, startStorage) | |
| return res, async, err | |
| } | |
| // Ensure legacy receives the same object returned by Storage to avoid divergence | |
| _, _, errObjectSt := d.Legacy.Update(ctx, name, &updateWrapper{upstream: objInfo, updated: res}, createValidation, updateValidation, forceAllowCreate, options) |
|
|
||
| func (d *DualWriterMode3) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) { | ||
| var method = "delete" | ||
| log := d.Log.WithValues("name", name, "kind", options.Kind, "method", method) |
There was a problem hiding this comment.
🔷 Medium: This loses the per-call fields (name/kind/method) by attaching the base logger instead of the enriched one; also the storage metrics label uses name instead of kind. Attach the enriched logger and use options.Kind for metrics consistency.
go
ctx = klog.NewContext(ctx, log)
// ...
d.recordStorageDuration(false, mode3Str, options.Kind, method, startStorage)
| startLegacy := time.Now() | ||
| ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("legacy deletecollection timeout")) | ||
| defer cancel() | ||
| _, err := d.Legacy.DeleteCollection(ctx, deleteValidation, options, listOptions) |
There was a problem hiding this comment.
🔷 Medium: This records legacy DeleteCollection timing using the storage metrics function; use the legacy recorder for correct attribution.
| _, err := d.Legacy.DeleteCollection(ctx, deleteValidation, options, listOptions) | |
| ```go | |
| d.recordLegacyDuration(err != nil, mode3Str, options.Kind, method, startLegacy) |
Mirrors ai-code-review-evaluation#6 for like-for-like benchmarking.
dual-storage-baselinedual-storage-enhancedOriginal PR excerpt: