Skip to content

Commit 6b8db36

Browse files
Merge pull request #402 from pace/external-dependencies
grpc: Return external dependencies to client
2 parents c28c300 + 4ab1bd3 commit 6b8db36

File tree

6 files changed

+89
-21
lines changed

6 files changed

+89
-21
lines changed

go.mod

+6-6
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ require (
2020
github.com/google/uuid v1.6.0
2121
github.com/gorilla/mux v1.8.1
2222
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1
23-
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0
23+
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0
2424
github.com/jpillora/backoff v1.0.0
2525
github.com/mattn/go-isatty v0.0.20
2626
github.com/minio/minio-go/v7 v7.0.7
@@ -38,9 +38,9 @@ require (
3838
github.com/uptrace/bun/dialect/pgdialect v1.2.9
3939
github.com/uptrace/bun/driver/pgdriver v1.2.9
4040
github.com/zenazn/goji v1.0.1
41-
golang.org/x/text v0.21.0
41+
golang.org/x/text v0.22.0
4242
google.golang.org/grpc v1.67.1
43-
google.golang.org/protobuf v1.34.2
43+
google.golang.org/protobuf v1.36.4
4444
)
4545

4646
require (
@@ -74,9 +74,9 @@ require (
7474
github.com/yuin/gopher-lua v1.1.0 // indirect
7575
go.opentelemetry.io/otel v1.34.0 // indirect
7676
go.opentelemetry.io/otel/trace v1.34.0 // indirect
77-
golang.org/x/crypto v0.32.0 // indirect
78-
golang.org/x/net v0.28.0 // indirect
79-
golang.org/x/sys v0.29.0 // indirect
77+
golang.org/x/crypto v0.33.0 // indirect
78+
golang.org/x/net v0.35.0 // indirect
79+
golang.org/x/sys v0.30.0 // indirect
8080
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
8181
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
8282
gopkg.in/ini.v1 v1.67.0 // indirect

go.sum

+14-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg=
2-
cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw=
32
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
43
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
54
github.com/PuerkitoBio/rehttp v1.4.0 h1:rIN7A2s+O9fmHUM1vUcInvlHj9Ysql4hE+Y0wcl/xk8=
@@ -79,8 +78,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
7978
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
8079
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
8180
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
82-
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0 h1:kQ0NI7W1B3HwiN5gAYtY+XFItDPbLBwYRxAqbFTyDes=
83-
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0/go.mod h1:zrT2dxOAjNFPRGjTUe2Xmb4q4YdUwVvQFV6xiCSf+z0=
81+
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 h1:FbSCl+KggFl+Ocym490i/EyXF4lPgLoUtcSWquBM0Rs=
82+
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc=
8483
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
8584
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
8685
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
@@ -209,19 +208,19 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
209208
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
210209
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
211210
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
212-
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
213-
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
211+
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
212+
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
214213
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
215214
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
216215
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
217216
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
218217
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
219-
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
220-
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
218+
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
219+
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
221220
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
222221
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
223-
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
224-
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
222+
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
223+
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
225224
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
226225
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
227226
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -235,14 +234,14 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
235234
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
236235
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
237236
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
238-
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
239-
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
237+
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
238+
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
240239
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
241240
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
242241
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
243242
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
244-
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
245-
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
243+
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
244+
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
246245
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
247246
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
248247
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -254,8 +253,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:
254253
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
255254
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
256255
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
257-
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
258-
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
256+
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
257+
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
259258
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
260259
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
261260
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=

grpc/client.go

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ func NewClient(addr string) (*grpc.ClientConn, error) {
3636

3737
opts := []grpc_retry.CallOption{
3838
grpc_retry.WithBackoff(grpc_retry.BackoffLinear(100 * time.Millisecond)),
39+
grpc_retry.WithMax(10),
3940
}
4041

4142
conn, err := grpc.NewClient(addr,

grpc/middleware.go

+20
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"encoding/gob"
88
"strings"
99

10+
"github.com/pace/bricks/http/middleware"
1011
"github.com/pace/bricks/pkg/tracking/utm"
1112
"google.golang.org/grpc/metadata"
1213
)
@@ -36,3 +37,22 @@ func EncodeContextWithUTMData(parentCtx context.Context) context.Context {
3637
}
3738
return metadata.AppendToOutgoingContext(parentCtx, utmMetadataKey, w.String())
3839
}
40+
41+
// AddExternalDependencyMetadataToContext adds external dependencies to the context if they are present in the metadata.
42+
func AddExternalDependencyMetadataToContext(ctx context.Context, md metadata.MD) context.Context {
43+
// If there are no external dependencies in the metadata, we can return the context as is.
44+
externalDependencies := md.Get(MetadataKeyExternalDependencies)
45+
if len(externalDependencies) == 0 {
46+
return ctx
47+
}
48+
49+
// If there are external dependencies in the metadata, we need to parse them and add them to the context.
50+
edc := middleware.ExternalDependencyContextFromContext(ctx)
51+
if edc == nil {
52+
edc = &middleware.ExternalDependencyContext{}
53+
}
54+
55+
edc.Parse(externalDependencies[0])
56+
57+
return middleware.ContextWithExternalDependency(ctx, edc)
58+
}

grpc/middleware_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"context"
77
"testing"
88

9+
"github.com/pace/bricks/http/middleware"
910
"github.com/pace/bricks/pkg/tracking/utm"
1011
"github.com/stretchr/testify/require"
1112
"google.golang.org/grpc/metadata"
@@ -31,3 +32,29 @@ func TestEncodeContextWithUTMData(t *testing.T) {
3132
require.True(t, exists)
3233
require.Equal(t, data, utmData)
3334
}
35+
36+
func TestAddExternalDependencyMetadataToContext(t *testing.T) {
37+
md := metadata.New(map[string]string{
38+
MetadataKeyExternalDependencies: "dep1:1,dep2:2,dep3:3",
39+
})
40+
ctx := context.Background()
41+
ctx = AddExternalDependencyMetadataToContext(ctx, md)
42+
edc := middleware.ExternalDependencyContextFromContext(ctx)
43+
require.NotNil(t, edc)
44+
require.Equal(t, "dep1:1,dep2:2,dep3:3", edc.String())
45+
46+
ctx = AddExternalDependencyMetadataToContext(ctx, metadata.New(map[string]string{
47+
MetadataKeyExternalDependencies: "dep4:4,dep5:5,dep6:6",
48+
}))
49+
edc = middleware.ExternalDependencyContextFromContext(ctx)
50+
require.NotNil(t, edc)
51+
require.Equal(t, "dep1:1,dep2:2,dep3:3,dep4:4,dep5:5,dep6:6", edc.String())
52+
}
53+
54+
func TestAddExternalDependencyMetadataToContext_NoDependencies(t *testing.T) {
55+
md := metadata.New(map[string]string{})
56+
ctx := context.Background()
57+
ctx = AddExternalDependencyMetadataToContext(ctx, md)
58+
edc := middleware.ExternalDependencyContextFromContext(ctx)
59+
require.Nil(t, edc)
60+
}

grpc/server.go

+21
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ func Server(ab AuthBackend, logger grpc_logging.Logger) *grpc.Server {
8888
start := time.Now()
8989
err := handler(srv, wrappedStream)
9090

91+
if err := addExternalDependencyToTrailer(ctx); err != nil {
92+
log.Ctx(ctx).Warn().Err(err).Msg("unable to add external dependencies to trailer")
93+
}
94+
9195
log.Ctx(ctx).Info().Str("method", info.FullMethod).
9296
Dur("duration", time.Since(start)).
9397
Str("type", "stream").
@@ -120,6 +124,10 @@ func Server(ab AuthBackend, logger grpc_logging.Logger) *grpc.Server {
120124
start := time.Now()
121125
resp, err = handler(ctx, req)
122126

127+
if err := addExternalDependencyToTrailer(ctx); err != nil {
128+
log.Ctx(ctx).Warn().Err(err).Msg("unable to add external dependencies to trailer")
129+
}
130+
123131
log.Ctx(ctx).Info().Str("method", info.FullMethod).
124132
Dur("duration", time.Since(start)).
125133
Str("type", "unary").
@@ -143,6 +151,19 @@ func Server(ab AuthBackend, logger grpc_logging.Logger) *grpc.Server {
143151
return myServer
144152
}
145153

154+
// addExternalDependencyToTrailer adds the external dependencies to the grpc trailer.
155+
// This is used to track external dependencies which are updated during the request lifecycle.
156+
func addExternalDependencyToTrailer(ctx context.Context) error {
157+
edc := middleware.ExternalDependencyContextFromContext(ctx)
158+
if edc == nil {
159+
return nil
160+
}
161+
162+
md := metadata.Pairs(MetadataKeyExternalDependencies, edc.String())
163+
164+
return grpc.SetTrailer(ctx, md)
165+
}
166+
146167
func prepareContext(ctx context.Context) (context.Context, metadata.MD) {
147168
md, _ := metadata.FromIncomingContext(ctx)
148169
logger := zlog.With().Logger()

0 commit comments

Comments
 (0)