From 22d39d2c47f6791b4b6322468b5ce3b4fa9fbbc4 Mon Sep 17 00:00:00 2001 From: Amirmohammad Sadat Shokouhi Date: Thu, 3 Sep 2026 10:43:16 +0330 Subject: [PATCH] internal/fwserver: Report semantic equality modification instead of comparing whole values ReadResource, CreateResource, UpdateResource and ReadDataSource decided whether semantic equality had changed anything by deep-comparing the entire returned value against the value they passed in. For a resource with a large set attribute that comparison is O(n^2) in the number of set elements, and it runs on every one of those RPCs. SchemaSemanticEquality already knows whether it replaced a value, so have it report that in the response and drop the comparison. The four expectations updated here predate the new field; in each of them the proposed value is "new" and the expected new value is "prior", so the data did change and the comparison they replace reached the same conclusion. --- .changes/unreleased/ENHANCEMENTS-20260903-103534.yaml | 6 ++++++ internal/fwserver/schema_semantic_equality.go | 9 +++++++++ internal/fwserver/schema_semantic_equality_test.go | 4 ++++ internal/fwserver/server_createresource.go | 2 +- internal/fwserver/server_readdatasource.go | 2 +- internal/fwserver/server_readresource.go | 2 +- internal/fwserver/server_updateresource.go | 2 +- 7 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 .changes/unreleased/ENHANCEMENTS-20260903-103534.yaml diff --git a/.changes/unreleased/ENHANCEMENTS-20260903-103534.yaml b/.changes/unreleased/ENHANCEMENTS-20260903-103534.yaml new file mode 100644 index 000000000..a9d4d385f --- /dev/null +++ b/.changes/unreleased/ENHANCEMENTS-20260903-103534.yaml @@ -0,0 +1,6 @@ +kind: ENHANCEMENTS +body: 'all: Improved performance of resource read, create and update and of data source + read by no longer deep-comparing the entire value to detect semantic equality changes' +time: 2026-09-03T10:35:34+03:30 +custom: + Issue: "1322" diff --git a/internal/fwserver/schema_semantic_equality.go b/internal/fwserver/schema_semantic_equality.go index 92c032c88..72465dc54 100644 --- a/internal/fwserver/schema_semantic_equality.go +++ b/internal/fwserver/schema_semantic_equality.go @@ -28,6 +28,11 @@ type SchemaSemanticEqualityResponse struct { // NewData is the new schema-based data after any modifications. NewData fwschemadata.Data + // Modified reports whether any value in NewData was replaced by its prior + // value. Callers use this instead of comparing NewData against the data + // they passed in, which is a deep comparison of the whole value. + Modified bool + // Diagnostics report errors or warnings related to running all attribute // plan modifiers. Returning an empty slice indicates a successful // plan modification with no warnings or errors generated. @@ -91,6 +96,8 @@ func SchemaSemanticEquality(ctx context.Context, req SchemaSemanticEqualityReque continue } + resp.Modified = true + resp.Diagnostics.Append(resp.NewData.SetAtPath(ctx, valueReq.Path, valueResp.NewValue)...) if resp.Diagnostics.HasError() { @@ -137,6 +144,8 @@ func SchemaSemanticEquality(ctx context.Context, req SchemaSemanticEqualityReque continue } + resp.Modified = true + resp.Diagnostics.Append(resp.NewData.SetAtPath(ctx, valueReq.Path, valueResp.NewValue)...) if resp.Diagnostics.HasError() { diff --git a/internal/fwserver/schema_semantic_equality_test.go b/internal/fwserver/schema_semantic_equality_test.go index dbddc41fd..28ecfd786 100644 --- a/internal/fwserver/schema_semantic_equality_test.go +++ b/internal/fwserver/schema_semantic_equality_test.go @@ -144,6 +144,7 @@ func TestSchemaSemanticEquality(t *testing.T) { }, }, expected: &fwserver.SchemaSemanticEqualityResponse{ + Modified: true, NewData: fwschemadata.Data{ Description: fwschemadata.DataDescriptionPlan, Schema: testschema.Schema{ @@ -619,6 +620,7 @@ func TestSchemaSemanticEquality(t *testing.T) { }, }, expected: &fwserver.SchemaSemanticEqualityResponse{ + Modified: true, NewData: fwschemadata.Data{ Description: fwschemadata.DataDescriptionPlan, Schema: testschema.Schema{ @@ -1325,6 +1327,7 @@ func TestSchemaSemanticEquality(t *testing.T) { }, }, expected: &fwserver.SchemaSemanticEqualityResponse{ + Modified: true, NewData: fwschemadata.Data{ Description: fwschemadata.DataDescriptionPlan, Schema: testschema.Schema{ @@ -1966,6 +1969,7 @@ func TestSchemaSemanticEquality(t *testing.T) { }, }, expected: &fwserver.SchemaSemanticEqualityResponse{ + Modified: true, NewData: fwschemadata.Data{ Description: fwschemadata.DataDescriptionPlan, Schema: testschema.Schema{ diff --git a/internal/fwserver/server_createresource.go b/internal/fwserver/server_createresource.go index 731000fa2..5768ee79d 100644 --- a/internal/fwserver/server_createresource.go +++ b/internal/fwserver/server_createresource.go @@ -204,7 +204,7 @@ func (s *Server) CreateResource(ctx context.Context, req *CreateResourceRequest, return } - if !semanticEqualityResp.NewData.TerraformValue.Equal(resp.NewState.Raw) { + if semanticEqualityResp.Modified { logging.FrameworkDebug(ctx, "State updated due to semantic equality") resp.NewState.Raw = semanticEqualityResp.NewData.TerraformValue diff --git a/internal/fwserver/server_readdatasource.go b/internal/fwserver/server_readdatasource.go index eab2c3b93..a76990d95 100644 --- a/internal/fwserver/server_readdatasource.go +++ b/internal/fwserver/server_readdatasource.go @@ -135,7 +135,7 @@ func (s *Server) ReadDataSource(ctx context.Context, req *ReadDataSourceRequest, return } - if semanticEqualityResp.NewData.TerraformValue.Equal(resp.State.Raw) { + if !semanticEqualityResp.Modified { return } diff --git a/internal/fwserver/server_readresource.go b/internal/fwserver/server_readresource.go index a60cad524..adf0e1cef 100644 --- a/internal/fwserver/server_readresource.go +++ b/internal/fwserver/server_readresource.go @@ -233,7 +233,7 @@ func (s *Server) ReadResource(ctx context.Context, req *ReadResourceRequest, res return } - if !semanticEqualityResp.NewData.TerraformValue.Equal(resp.NewState.Raw) { + if semanticEqualityResp.Modified { logging.FrameworkDebug(ctx, "State updated due to semantic equality") resp.NewState.Raw = semanticEqualityResp.NewData.TerraformValue diff --git a/internal/fwserver/server_updateresource.go b/internal/fwserver/server_updateresource.go index fe4089f9b..ee837838b 100644 --- a/internal/fwserver/server_updateresource.go +++ b/internal/fwserver/server_updateresource.go @@ -234,7 +234,7 @@ func (s *Server) UpdateResource(ctx context.Context, req *UpdateResourceRequest, return } - if !semanticEqualityResp.NewData.TerraformValue.Equal(resp.NewState.Raw) { + if semanticEqualityResp.Modified { logging.FrameworkDebug(ctx, "State updated due to semantic equality") resp.NewState.Raw = semanticEqualityResp.NewData.TerraformValue