-
Notifications
You must be signed in to change notification settings - Fork 1
Cloud-SDK extraction — Phase A: IaCStateBackend proto + benchmark + proto-lock #669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
d2cd4c5
docs(plans): cloud-SDK extraction design — workflow core → strict-con…
intel352 98448d5
docs(plans): cloud-SDK extraction design — adversarial review cycle 1…
intel352 18534e8
docs(plans): cloud-SDK extraction design — adversarial review cycle 2…
intel352 5fb2000
docs(plans): fix stale Phase A/B refs + Status line post-cycle-2
intel352 39a3b43
docs(plans): cloud-SDK extraction design — adversarial review cycle 3…
intel352 a6d6396
docs(plans): cloud-SDK extraction design — adversarial review cycle 4…
intel352 e71fa10
docs(plans): cloud-SDK extraction design — adversarial review cycle 5…
intel352 ac10b67
docs(plans): cloud-SDK extraction design — adversarial review cycle 6…
intel352 808ec51
docs(plans): cloud-SDK extraction design — adversarial review cycle 7…
intel352 337d0e0
docs(plans): cloud-SDK extraction design — cycle-8 re-baseline agains…
intel352 b9facf5
docs(plans): cloud-SDK extraction design — cycle-9 re-baseline + audi…
intel352 264791b
docs(plans): cloud-SDK extraction design — cycle-10 re-baseline, AWS …
intel352 1b8fb38
docs(plans): cloud-SDK extraction design — cycle-11 PASS, minor cleanups
intel352 a81f0b6
fix(scripts): audit-cloud-symbols single-line-import grep poisoned th…
intel352 02fe621
docs(plans): cloud-SDK extraction implementation plan (Phase 0 + Phas…
intel352 3499c8b
docs(plans): cloud-SDK extraction plan — address plan-phase adversari…
intel352 e34be7c
docs(plans): cloud-SDK extraction plan — plan-review cycle 2 fixes
intel352 bdf0de8
docs(plans): cloud-SDK extraction plan — plan-review cycle 3 PASS + m…
intel352 e67757c
chore: lock scope for cloud-sdk-extraction (alignment passed)
intel352 cdc2694
refactor(module): split platform_kubernetes_kind.go into _core + _gke
intel352 c220beb
docs(module): add file-purpose headers to platform_kubernetes _core/_gke
intel352 443f495
docs(module): fix stale 'Requires the Azure SDK' comment on aksBackend
intel352 bf203f4
ci(audit): enforce k8s-backend init() partition + run audit on every PR
intel352 67c8b0a
docs(plans): IaCStateBackend transport benchmark result — decision pe…
intel352 20d7fbb
docs(plans): Task 6 resolved — unary IaCStateBackend LOCKED (operator…
intel352 6062520
Revert "chore: lock scope for cloud-sdk-extraction (alignment passed)"
intel352 2bbe60f
docs(plans): amend cloud-sdk-extraction plan — PR 6 (ctx) + de-gate PR 4
intel352 bfa06e6
chore: re-lock scope for cloud-sdk-extraction (amended — alignment re…
intel352 a3759d2
feat(proto): add IaCStateBackend service to iac.proto
intel352 fc333a0
test(module): add IaCStateBackend gRPC-vs-in-process benchmark harness
intel352 7da06cf
test(wftest): add IaCStateBackend to iacServiceChecks coverage table
intel352 6dbf1d2
fix(iac-bench): validate SaveState input, close bufconn, broaden impo…
intel352 246d923
Merge remote-tracking branch 'origin/main' into feat/cloud-sdk-extrac…
intel352 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| package module | ||
|
|
||
| import ( | ||
| "context" | ||
| "encoding/json" | ||
| "net" | ||
| "strconv" | ||
| "strings" | ||
| "testing" | ||
|
|
||
| pb "github.com/GoCodeAlone/workflow/plugin/external/proto" | ||
| "google.golang.org/grpc" | ||
| "google.golang.org/grpc/codes" | ||
| "google.golang.org/grpc/credentials/insecure" | ||
| "google.golang.org/grpc/status" | ||
| "google.golang.org/grpc/test/bufconn" | ||
| ) | ||
|
|
||
| // oneMBState builds an IaCState whose JSON payload is ~1 MB (Outputs map padded). | ||
| func oneMBState() *IaCState { | ||
| big := strings.Repeat("x", 1024) | ||
| outputs := make(map[string]any, 1024) | ||
| for i := 0; i < 1024; i++ { | ||
| outputs["k"+strconv.Itoa(i)] = big | ||
| } | ||
| return &IaCState{ | ||
| ResourceID: "bench-resource", ResourceType: "kubernetes", Provider: "azure", | ||
| Status: "active", Outputs: outputs, Config: map[string]any{"size": "large"}, | ||
| CreatedAt: "2026-05-14T00:00:00Z", UpdatedAt: "2026-05-14T00:00:00Z", | ||
| } | ||
| } | ||
|
|
||
| // benchStateToProto — local, self-contained IaCState -> pb.IaCState converter. | ||
| // Task 7 replaces this with the production iacStateToProto. | ||
| func benchStateToProto(s *IaCState) *pb.IaCState { | ||
| outJSON, _ := json.Marshal(s.Outputs) | ||
| cfgJSON, _ := json.Marshal(s.Config) | ||
| return &pb.IaCState{ | ||
| ResourceId: s.ResourceID, ResourceType: s.ResourceType, Provider: s.Provider, | ||
| Status: s.Status, OutputsJson: outJSON, ConfigJson: cfgJSON, | ||
| CreatedAt: s.CreatedAt, UpdatedAt: s.UpdatedAt, | ||
| } | ||
| } | ||
|
|
||
| // benchStateBackendServer wraps an IaCStateStore behind pb.IaCStateBackendServer. | ||
| // Task 7 promotes this to the production iacStateBackendServer. | ||
| type benchStateBackendServer struct { | ||
| pb.UnimplementedIaCStateBackendServer | ||
| store IaCStateStore | ||
| } | ||
|
|
||
| func (s *benchStateBackendServer) GetState(_ context.Context, r *pb.GetStateRequest) (*pb.GetStateResponse, error) { | ||
| st, err := s.store.GetState(r.ResourceId) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if st == nil { | ||
| return &pb.GetStateResponse{Exists: false}, nil | ||
| } | ||
| return &pb.GetStateResponse{Exists: true, State: benchStateToProto(st)}, nil | ||
| } | ||
| func (s *benchStateBackendServer) SaveState(_ context.Context, r *pb.SaveStateRequest) (*pb.SaveStateResponse, error) { | ||
| if r.State == nil { | ||
| return nil, status.Error(codes.InvalidArgument, "SaveState: request State is nil") | ||
| } | ||
| var outputs, config map[string]any | ||
| if len(r.State.OutputsJson) > 0 { | ||
| if err := json.Unmarshal(r.State.OutputsJson, &outputs); err != nil { | ||
| return nil, status.Errorf(codes.InvalidArgument, "SaveState: invalid OutputsJson: %v", err) | ||
| } | ||
| } | ||
| if len(r.State.ConfigJson) > 0 { | ||
| if err := json.Unmarshal(r.State.ConfigJson, &config); err != nil { | ||
| return nil, status.Errorf(codes.InvalidArgument, "SaveState: invalid ConfigJson: %v", err) | ||
| } | ||
| } | ||
| return &pb.SaveStateResponse{}, s.store.SaveState(&IaCState{ | ||
| ResourceID: r.State.ResourceId, ResourceType: r.State.ResourceType, | ||
| Provider: r.State.Provider, Status: r.State.Status, Outputs: outputs, Config: config, | ||
| }) | ||
| } | ||
| func (s *benchStateBackendServer) Lock(_ context.Context, r *pb.LockRequest) (*pb.LockResponse, error) { | ||
| return &pb.LockResponse{}, s.store.Lock(r.ResourceId) | ||
| } | ||
| func (s *benchStateBackendServer) Unlock(_ context.Context, r *pb.UnlockRequest) (*pb.UnlockResponse, error) { | ||
| return &pb.UnlockResponse{}, s.store.Unlock(r.ResourceId) | ||
| } | ||
| func (s *benchStateBackendServer) ListStates(_ context.Context, _ *pb.ListStatesRequest) (*pb.ListStatesResponse, error) { | ||
| return &pb.ListStatesResponse{}, nil | ||
| } | ||
| func (s *benchStateBackendServer) DeleteState(_ context.Context, r *pb.DeleteStateRequest) (*pb.DeleteStateResponse, error) { | ||
| return &pb.DeleteStateResponse{}, s.store.DeleteState(r.ResourceId) | ||
| } | ||
|
|
||
| // BenchmarkIaCStateBackend_InProcess is the baseline: direct IaCStateStore calls. | ||
| func BenchmarkIaCStateBackend_InProcess(b *testing.B) { | ||
| store := NewMemoryIaCStateStore() | ||
| st := oneMBState() | ||
| b.ResetTimer() | ||
| for i := 0; i < b.N; i++ { | ||
| if err := store.Lock(st.ResourceID); err != nil { | ||
| b.Fatal(err) | ||
| } | ||
| if _, err := store.GetState(st.ResourceID); err != nil { | ||
| b.Fatal(err) | ||
| } | ||
| if err := store.SaveState(st); err != nil { | ||
| b.Fatal(err) | ||
| } | ||
| if err := store.Unlock(st.ResourceID); err != nil { | ||
| b.Fatal(err) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // BenchmarkIaCStateBackend_GRPC is the post-extraction path: same store, same | ||
| // cycle, but every call crosses a real (in-memory bufconn) gRPC boundary. | ||
| func BenchmarkIaCStateBackend_GRPC(b *testing.B) { | ||
| // 4 MiB in-memory listener buffer. Note: this sizes the bufconn pipe only; | ||
| // gRPC's own max message size is configured separately via dial/server options. | ||
| lis := bufconn.Listen(4 << 20) | ||
| defer lis.Close() | ||
| srv := grpc.NewServer() | ||
| pb.RegisterIaCStateBackendServer(srv, &benchStateBackendServer{store: NewMemoryIaCStateStore()}) | ||
| go func() { _ = srv.Serve(lis) }() | ||
| defer srv.Stop() | ||
|
|
||
| conn, err := grpc.NewClient("passthrough:///bufnet", | ||
| grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { return lis.DialContext(ctx) }), | ||
| grpc.WithTransportCredentials(insecure.NewCredentials())) | ||
| if err != nil { | ||
| b.Fatal(err) | ||
| } | ||
| defer conn.Close() | ||
| client := pb.NewIaCStateBackendClient(conn) | ||
| st := oneMBState() | ||
| pbState := benchStateToProto(st) | ||
| ctx := context.Background() | ||
| b.ResetTimer() | ||
| for i := 0; i < b.N; i++ { | ||
| if _, err := client.Lock(ctx, &pb.LockRequest{ResourceId: st.ResourceID}); err != nil { | ||
| b.Fatal(err) | ||
| } | ||
| if _, err := client.GetState(ctx, &pb.GetStateRequest{ResourceId: st.ResourceID}); err != nil { | ||
| b.Fatal(err) | ||
| } | ||
| if _, err := client.SaveState(ctx, &pb.SaveStateRequest{State: pbState}); err != nil { | ||
| b.Fatal(err) | ||
| } | ||
| if _, err := client.Unlock(ctx, &pb.UnlockRequest{ResourceId: st.ResourceID}); err != nil { | ||
| b.Fatal(err) | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.