diff --git a/internal/pluginhost/adapters_test.go b/internal/pluginhost/adapters_test.go index de62918e..302b1f38 100644 --- a/internal/pluginhost/adapters_test.go +++ b/internal/pluginhost/adapters_test.go @@ -2234,6 +2234,39 @@ func TestUsageAdapterPanicFusesPlugin(t *testing.T) { } } +func TestUsageAdapterDetachesCanceledRequestContext(t *testing.T) { + type contextKey struct{} + const contextValue = "usage-context-value" + + called := 0 + plugin := usagePluginFunc(func(ctx context.Context, record pluginapi.UsageRecord) { + called++ + if errContext := ctx.Err(); errContext != nil { + t.Fatalf("usage context error = %v, want nil", errContext) + } + if value := ctx.Value(contextKey{}); value != contextValue { + t.Fatalf("usage context value = %v, want %q", value, contextValue) + } + }) + host := newHostWithRecords(capabilityRecord{ + id: "usage-canceled-context", + plugin: pluginapi.Plugin{Capabilities: pluginapi.Capabilities{ + UsagePlugin: plugin, + }}, + }) + adapter := &usageAdapter{ + host: host, + pluginID: "usage-canceled-context", + } + + ctx, cancel := context.WithCancel(context.WithValue(context.Background(), contextKey{}, contextValue)) + cancel() + adapter.HandleUsage(ctx, coreusage.Record{Provider: "plugin-provider"}) + if called != 1 { + t.Fatalf("usage plugin calls = %d, want 1", called) + } +} + func TestUsageAdapterNormalizesOmittedGenerateToTrue(t *testing.T) { var gotGenerate bool plugin := usagePluginFunc(func(ctx context.Context, record pluginapi.UsageRecord) { diff --git a/internal/pluginhost/adapters_usage_translation.go b/internal/pluginhost/adapters_usage_translation.go index 2201eb6c..93a4c8a5 100644 --- a/internal/pluginhost/adapters_usage_translation.go +++ b/internal/pluginhost/adapters_usage_translation.go @@ -132,6 +132,11 @@ func (a *usageAdapter) HandleUsage(ctx context.Context, record coreusage.Record) if a == nil { return } + if ctx == nil { + ctx = context.Background() + } else { + ctx = context.WithoutCancel(ctx) + } plugin := a.host.currentUsagePlugin(a.pluginID) if plugin == nil { return