From c7742e4c6f3cd786356026939a98c696d26dc860 Mon Sep 17 00:00:00 2001 From: JH Date: Mon, 24 Aug 2026 19:09:50 -0700 Subject: [PATCH 1/2] Pass a closure to visitDataBlobs visitDataBlobs, translateDataBlobs and translateOneDataBlob took a stringMatcher and a visitor function and passed both down to the events inside the blob. They now take one blobVisitor closure, and the two callers wrap their existing call in it. No behaviour change, and no test needed updating. Co-Authored-By: Claude Opus 5 --- interceptor/reflection.go | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/interceptor/reflection.go b/interceptor/reflection.go index 9f836fa4..fc5e02e3 100644 --- a/interceptor/reflection.go +++ b/interceptor/reflection.go @@ -137,6 +137,11 @@ type stringMatcher func(name string) (string, bool) // It returns whether anything was matched and any error it encountered. type visitor func(logger log.Logger, obj any, match stringMatcher) (bool, error) +// blobVisitor visits the history events deserialized from a data blob. Callers close over +// whatever matching state they need, since a data blob starts a fresh traversal that cannot +// see the enclosing message. +type blobVisitor func(events []*history.HistoryEvent) (bool, error) + // visitNamespace uses reflection to recursively visit all fields // in the given object. When it finds namespace string fields, it invokes // the provided match function. @@ -180,7 +185,9 @@ func visitNamespace(logger log.Logger, obj any, match stringMatcher) (bool, erro } return visit.Skip, nil } else if dataBlobFieldNames[fieldType.Name] { - changed, err := visitDataBlobs(logger, vwp, match, visitNamespace) + changed, err := visitDataBlobs(logger, vwp, func(events []*history.HistoryEvent) (bool, error) { + return visitNamespace(logger, events, match) + }) matched = matched || changed if err != nil { return visit.Stop, err @@ -225,7 +232,9 @@ func visitSearchAttributes(logger log.Logger, obj any, match stringMatcher) (boo return action, nil } if dataBlobFieldNames[fieldType.Name] { - changed, err := visitDataBlobs(logger, vwp, match, visitSearchAttributes) + changed, err := visitDataBlobs(logger, vwp, func(events []*history.HistoryEvent) (bool, error) { + return visitSearchAttributes(logger, events, match) + }) matched = matched || changed if err != nil { return visit.Stop, err @@ -287,10 +296,10 @@ func getParentFieldType(vwp visit.ValueWithParent) (result reflect.StructField, return fieldType, action } -func visitDataBlobs(logger log.Logger, vwp visit.ValueWithParent, match stringMatcher, visitor visitor) (bool, error) { +func visitDataBlobs(logger log.Logger, vwp visit.ValueWithParent, bv blobVisitor) (bool, error) { switch evt := vwp.Interface().(type) { case []*common.DataBlob: - newEvts, matched, changed, err := translateDataBlobs(logger, match, visitor, evt...) + newEvts, matched, changed, err := translateDataBlobs(logger, bv, evt...) if err != nil { return matched, err } @@ -301,7 +310,7 @@ func visitDataBlobs(logger log.Logger, vwp visit.ValueWithParent, match stringMa } return matched, nil case *common.DataBlob: - newEvt, matched, changed, err := translateOneDataBlob(logger, match, visitor, evt) + newEvt, matched, changed, err := translateOneDataBlob(logger, bv, evt) if err != nil { return matched, err } @@ -316,9 +325,9 @@ func visitDataBlobs(logger log.Logger, vwp visit.ValueWithParent, match stringMa } } -func translateDataBlobs(logger log.Logger, match stringMatcher, visitor visitor, blobs ...*common.DataBlob) (result []*common.DataBlob, anyMatched, anyChanged bool, retErr error) { +func translateDataBlobs(logger log.Logger, bv blobVisitor, blobs ...*common.DataBlob) (result []*common.DataBlob, anyMatched, anyChanged bool, retErr error) { for i, blob := range blobs { - newBlob, matched, changed, err := translateOneDataBlob(logger, match, visitor, blob) + newBlob, matched, changed, err := translateOneDataBlob(logger, bv, blob) anyChanged = anyChanged || changed anyMatched = anyMatched || matched if err != nil { @@ -329,7 +338,7 @@ func translateDataBlobs(logger log.Logger, match stringMatcher, visitor visitor, return blobs, anyMatched, anyChanged, nil } -func translateOneDataBlob(logger log.Logger, match stringMatcher, visitor visitor, blob *common.DataBlob) (result *common.DataBlob, matched, changed bool, retErr error) { +func translateOneDataBlob(logger log.Logger, bv blobVisitor, blob *common.DataBlob) (result *common.DataBlob, matched, changed bool, retErr error) { if blob == nil || len(blob.Data) == 0 { return blob, matched, changed, nil } @@ -356,7 +365,7 @@ func translateOneDataBlob(logger log.Logger, match stringMatcher, visitor visito } } - m, err := visitor(logger, events, match) + m, err := bv(events) matched = matched || m if err != nil { return blob, matched, changed, err From 58b0f7d1f961376c53fcf6ce97702261018cc327 Mon Sep 17 00:00:00 2001 From: JH Date: Mon, 24 Aug 2026 19:16:15 -0700 Subject: [PATCH 2/2] Name the blob visitor parameter visitEvents bv was too short to read. Co-Authored-By: Claude Opus 5 --- interceptor/reflection.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/interceptor/reflection.go b/interceptor/reflection.go index fc5e02e3..e1c19c73 100644 --- a/interceptor/reflection.go +++ b/interceptor/reflection.go @@ -296,10 +296,10 @@ func getParentFieldType(vwp visit.ValueWithParent) (result reflect.StructField, return fieldType, action } -func visitDataBlobs(logger log.Logger, vwp visit.ValueWithParent, bv blobVisitor) (bool, error) { +func visitDataBlobs(logger log.Logger, vwp visit.ValueWithParent, visitEvents blobVisitor) (bool, error) { switch evt := vwp.Interface().(type) { case []*common.DataBlob: - newEvts, matched, changed, err := translateDataBlobs(logger, bv, evt...) + newEvts, matched, changed, err := translateDataBlobs(logger, visitEvents, evt...) if err != nil { return matched, err } @@ -310,7 +310,7 @@ func visitDataBlobs(logger log.Logger, vwp visit.ValueWithParent, bv blobVisitor } return matched, nil case *common.DataBlob: - newEvt, matched, changed, err := translateOneDataBlob(logger, bv, evt) + newEvt, matched, changed, err := translateOneDataBlob(logger, visitEvents, evt) if err != nil { return matched, err } @@ -325,9 +325,9 @@ func visitDataBlobs(logger log.Logger, vwp visit.ValueWithParent, bv blobVisitor } } -func translateDataBlobs(logger log.Logger, bv blobVisitor, blobs ...*common.DataBlob) (result []*common.DataBlob, anyMatched, anyChanged bool, retErr error) { +func translateDataBlobs(logger log.Logger, visitEvents blobVisitor, blobs ...*common.DataBlob) (result []*common.DataBlob, anyMatched, anyChanged bool, retErr error) { for i, blob := range blobs { - newBlob, matched, changed, err := translateOneDataBlob(logger, bv, blob) + newBlob, matched, changed, err := translateOneDataBlob(logger, visitEvents, blob) anyChanged = anyChanged || changed anyMatched = anyMatched || matched if err != nil { @@ -338,7 +338,7 @@ func translateDataBlobs(logger log.Logger, bv blobVisitor, blobs ...*common.Data return blobs, anyMatched, anyChanged, nil } -func translateOneDataBlob(logger log.Logger, bv blobVisitor, blob *common.DataBlob) (result *common.DataBlob, matched, changed bool, retErr error) { +func translateOneDataBlob(logger log.Logger, visitEvents blobVisitor, blob *common.DataBlob) (result *common.DataBlob, matched, changed bool, retErr error) { if blob == nil || len(blob.Data) == 0 { return blob, matched, changed, nil } @@ -365,7 +365,7 @@ func translateOneDataBlob(logger log.Logger, bv blobVisitor, blob *common.DataBl } } - m, err := bv(events) + m, err := visitEvents(events) matched = matched || m if err != nil { return blob, matched, changed, err