4
0
Эх сурвалжийг харах

fix: deep-clone ActionBinding when copying log entries

Callers mutating Binding.ID or OnDashboards no longer race with
executor-owned state returned from GetLog helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>
jamesread 1 өдөр өмнө
parent
commit
4c4cb7452f

+ 12 - 0
service/internal/executor/executor.go

@@ -153,6 +153,17 @@ type InternalLogEntry struct {
 	TimedOut            bool
 }
 
+func cloneActionBinding(binding *ActionBinding) *ActionBinding {
+	if binding == nil {
+		return nil
+	}
+
+	cloned := *binding
+	cloned.OnDashboards = slices.Clone(binding.OnDashboards)
+
+	return &cloned
+}
+
 func cloneInternalLogEntry(entry *InternalLogEntry) *InternalLogEntry {
 	if entry == nil {
 		return nil
@@ -161,6 +172,7 @@ func cloneInternalLogEntry(entry *InternalLogEntry) *InternalLogEntry {
 	cloned := *entry
 	cloned.Arguments = maps.Clone(entry.Arguments)
 	cloned.Tags = slices.Clone(entry.Tags)
+	cloned.Binding = cloneActionBinding(entry.Binding)
 
 	return &cloned
 }

+ 11 - 0
service/internal/executor/executor_test.go

@@ -44,6 +44,12 @@ func TestGetLogReturnsDefensiveCopy(t *testing.T) {
 		Arguments: map[string]string{"message": "original"},
 		Output:    "original",
 		Tags:      []string{"original"},
+		Binding: &ActionBinding{
+			ID: "original-binding",
+			OnDashboards: []DashboardNavigationTarget{
+				{Title: "original"},
+			},
+		},
 	}
 
 	entry, found := e.GetLog("tracking-id")
@@ -52,12 +58,17 @@ func TestGetLogReturnsDefensiveCopy(t *testing.T) {
 	entry.Arguments["message"] = "changed"
 	entry.Output = "changed"
 	entry.Tags[0] = "changed"
+	entry.Binding.ID = "changed-binding"
+	entry.Binding.OnDashboards[0].Title = "changed"
 
 	stored, found := e.GetLog("tracking-id")
 	require.True(t, found)
 	assert.Equal(t, "original", stored.Arguments["message"])
 	assert.Equal(t, "original", stored.Output)
 	assert.Equal(t, []string{"original"}, stored.Tags)
+	require.NotNil(t, stored.Binding)
+	assert.Equal(t, "original-binding", stored.Binding.ID)
+	assert.Equal(t, []DashboardNavigationTarget{{Title: "original"}}, stored.Binding.OnDashboards)
 }
 
 func TestCreateExecutorAndExec(t *testing.T) {