Skip to content

Commit ada7f9b

Browse files
pkcllcursoragent
andcommitted
Add NewEventWithOpts and bump pkg/chipingress for resource attributes.
Introduce NewEventWithOpts for variadic EventOpt without changing NewEvent's exported signature, update beholder call sites, and bump the root module's pkg/chipingress dependency to include the new API. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent e971983 commit ada7f9b

6 files changed

Lines changed: 38 additions & 11 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ require (
4343
github.com/scylladb/go-reflectx v1.0.1
4444
github.com/shopspring/decimal v1.4.0
4545
github.com/smartcontractkit/chain-selectors v1.0.100
46-
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62
46+
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260702050624-0fdeba8160d9
4747
github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4
4848
github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b
4949
github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b

go.sum

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/beholder/batch_emitter_service.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ func (e *ChipIngressBatchEmitterService) emitInternal(ctx context.Context, body
138138

139139
attributes := newAttributes(attrKVs...)
140140

141-
event, err := chipingress.NewEvent(domain, entity, body, attributes, chipingress.WithResourceAttributeExtensions(e.resourceAttrs))
141+
event, err := chipingress.NewEventWithOpts(domain, entity, body, attributes, chipingress.WithResourceAttributeExtensions(e.resourceAttrs))
142142
if err != nil {
143143
return fmt.Errorf("failed to create CloudEvent: %w", err)
144144
}

pkg/beholder/chip_ingress_emitter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (c *ChipIngressEmitter) Emit(ctx context.Context, body []byte, attrKVs ...a
7070
return err
7171
}
7272

73-
event, err := chipingress.NewEvent(sourceDomain, entityType, body, newAttributes(attrKVs...), chipingress.WithResourceAttributeExtensions(c.resourceAttrs))
73+
event, err := chipingress.NewEventWithOpts(sourceDomain, entityType, body, newAttributes(attrKVs...), chipingress.WithResourceAttributeExtensions(c.resourceAttrs))
7474
if err != nil {
7575
return err
7676
}

pkg/chipingress/client.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,13 @@ func WithResourceAttributeExtensions(attrs map[string]string) EventOpt {
324324
}
325325

326326
// NewEvent creates a new CloudEvent with the specified domain, entity, payload, and optional attributes.
327-
func NewEvent(domain, entity string, payload []byte, attributes map[string]any, opts ...EventOpt) (CloudEvent, error) {
327+
func NewEvent(domain, entity string, payload []byte, attributes map[string]any) (CloudEvent, error) {
328+
return NewEventWithOpts(domain, entity, payload, attributes)
329+
}
330+
331+
// NewEventWithOpts creates a new CloudEvent like NewEvent, additionally applying opts (e.g.
332+
// WithResourceAttributeExtensions) to the event before its data is set.
333+
func NewEventWithOpts(domain, entity string, payload []byte, attributes map[string]any, opts ...EventOpt) (CloudEvent, error) {
328334
event := ce.NewEvent()
329335
event.SetSource(domain)
330336
event.SetType(entity)

pkg/chipingress/client_test.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,12 @@ func TestSanitizeExtensionName(t *testing.T) {
189189
}
190190
}
191191

192-
func TestNewEvent_WithResourceAttributeExtensions(t *testing.T) {
192+
func TestNewEventWithOpts_WithResourceAttributeExtensions(t *testing.T) {
193193
payload := []byte("body")
194194

195195
t.Run("sanitized keys/values land on the event", func(t *testing.T) {
196196
attrs := map[string]string{"chain_id": "1", "k8s.pod.name": "pod-abc"}
197-
event, err := NewEvent("domain", "entity", payload, nil, WithResourceAttributeExtensions(attrs))
197+
event, err := NewEventWithOpts("domain", "entity", payload, nil, WithResourceAttributeExtensions(attrs))
198198
require.NoError(t, err)
199199
ext := event.Extensions()
200200
assert.Equal(t, "1", ext["chainid"])
@@ -203,14 +203,14 @@ func TestNewEvent_WithResourceAttributeExtensions(t *testing.T) {
203203

204204
t.Run("empty sanitized name is dropped", func(t *testing.T) {
205205
attrs := map[string]string{"---": "value"}
206-
event, err := NewEvent("domain", "entity", payload, nil, WithResourceAttributeExtensions(attrs))
206+
event, err := NewEventWithOpts("domain", "entity", payload, nil, WithResourceAttributeExtensions(attrs))
207207
require.NoError(t, err)
208208
assert.Len(t, event.Extensions(), 1) // only the always-set recordedtime extension
209209
})
210210

211211
t.Run("reserved name is skipped", func(t *testing.T) {
212212
attrs := map[string]string{IdempotencyKeyAttr: "should-not-override", "subject": "should-not-override"}
213-
event, err := NewEvent("domain", "entity", payload, map[string]any{IdempotencyKeyAttr: "real-key"}, WithResourceAttributeExtensions(attrs))
213+
event, err := NewEventWithOpts("domain", "entity", payload, map[string]any{IdempotencyKeyAttr: "real-key"}, WithResourceAttributeExtensions(attrs))
214214
require.NoError(t, err)
215215
ext := event.Extensions()
216216
assert.Equal(t, "real-key", ext[IdempotencyKeyAttr])
@@ -219,19 +219,38 @@ func TestNewEvent_WithResourceAttributeExtensions(t *testing.T) {
219219

220220
t.Run("duplicate sanitized names resolve deterministically to sorted-first key", func(t *testing.T) {
221221
attrs := map[string]string{"service.name": "from-dotted", "service_name": "from-snake"}
222-
event, err := NewEvent("domain", "entity", payload, nil, WithResourceAttributeExtensions(attrs))
222+
event, err := NewEventWithOpts("domain", "entity", payload, nil, WithResourceAttributeExtensions(attrs))
223223
require.NoError(t, err)
224224
// sorted order: "service.name" < "service_name" ('.' < '_' in ASCII), so the dotted key wins.
225225
assert.Equal(t, "from-dotted", event.Extensions()["servicename"])
226226
})
227227

228-
t.Run("omitting the opt is a no-op", func(t *testing.T) {
229-
event, err := NewEvent("domain", "entity", payload, nil)
228+
t.Run("omitting all opts is a no-op", func(t *testing.T) {
229+
event, err := NewEventWithOpts("domain", "entity", payload, nil)
230230
require.NoError(t, err)
231231
assert.Len(t, event.Extensions(), 1) // only the always-set recordedtime extension
232232
})
233233
}
234234

235+
// TestNewEvent_UnchangedSignature is a backward-compatibility guard: NewEvent's exported
236+
// signature must stay exactly as it was before EventOpt/NewEventWithOpts were introduced, and
237+
// must remain equivalent to calling NewEventWithOpts with no opts.
238+
func TestNewEvent_UnchangedSignature(t *testing.T) {
239+
payload := []byte("body")
240+
attributes := map[string]any{"subject": "example-subject"}
241+
242+
viaNewEvent, err := NewEvent("domain", "entity", payload, attributes)
243+
require.NoError(t, err)
244+
245+
viaNewEventWithOpts, err := NewEventWithOpts("domain", "entity", payload, attributes)
246+
require.NoError(t, err)
247+
248+
assert.Equal(t, viaNewEventWithOpts.Subject(), viaNewEvent.Subject())
249+
assert.Equal(t, viaNewEventWithOpts.Extensions()["recordedtime"].(ce.Timestamp).Time.Truncate(time.Second),
250+
viaNewEvent.Extensions()["recordedtime"].(ce.Timestamp).Time.Truncate(time.Second))
251+
assert.Equal(t, viaNewEventWithOpts.Data(), viaNewEvent.Data())
252+
}
253+
235254
func TestEventToProto(t *testing.T) {
236255
// Create a test protobuf message
237256
testProto := pb.PingResponse{Message: "test message"}

0 commit comments

Comments
 (0)