@@ -21,6 +21,8 @@ import (
2121 "context"
2222 "fmt"
2323 "os"
24+ "strconv"
25+ "time"
2426
2527 "cloud.google.com/go/bigtable/internal"
2628 "cloud.google.com/go/internal/version"
@@ -46,6 +48,11 @@ func mergeOutgoingMetadata(ctx context.Context, mds ...metadata.MD) context.Cont
4648 return metadata .NewOutgoingContext (ctx , metadata .Join (mds ... ))
4749}
4850
51+ // withClientAttemptEpochUsec sets the client epoch in usec.
52+ func withClientAttemptEpochUsec () metadata.MD {
53+ return metadata .Pairs ("bigtable-client-attempt-epoch-usec" , strconv .FormatInt (time .Now ().UnixMicro (), 10 ))
54+ }
55+
4956// withGoogleClientInfo sets the name and version of the application in
5057// the `x-goog-api-client` header passed on each request. Intended for
5158// use by Google-written clients.
@@ -67,15 +74,15 @@ func withGoogleClientInfo() metadata.MD {
6774// client to inject Google client information into the context metadata for
6875// streaming RPCs.
6976func streamInterceptor (ctx context.Context , desc * grpc.StreamDesc , cc * grpc.ClientConn , method string , streamer grpc.Streamer , opts ... grpc.CallOption ) (grpc.ClientStream , error ) {
70- ctx = mergeOutgoingMetadata (ctx , withGoogleClientInfo ())
77+ ctx = mergeOutgoingMetadata (ctx , withGoogleClientInfo (), withClientAttemptEpochUsec () )
7178 return streamer (ctx , desc , cc , method , opts ... )
7279}
7380
7481// unaryInterceptor intercepts the creation of UnaryInvoker within the bigtable
7582// client to inject Google client information into the context metadata for
7683// unary RPCs.
7784func unaryInterceptor (ctx context.Context , method string , req , reply interface {}, cc * grpc.ClientConn , invoker grpc.UnaryInvoker , opts ... grpc.CallOption ) error {
78- ctx = mergeOutgoingMetadata (ctx , withGoogleClientInfo ())
85+ ctx = mergeOutgoingMetadata (ctx , withGoogleClientInfo (), withClientAttemptEpochUsec () )
7986 return invoker (ctx , method , req , reply , cc , opts ... )
8087}
8188
0 commit comments