44 "context"
55 "errors"
66 "fmt"
7+ "time"
78
89 "go.opentelemetry.io/otel/metric"
910 "google.golang.org/grpc"
@@ -17,6 +18,9 @@ import (
1718 linkingclient "github.com/smartcontractkit/chainlink-protos/linking-service/go/v1"
1819)
1920
21+ // defaultRequestTimeout bounds Get(); callers sit in capability hot paths, so a hung connection must not propagate.
22+ const defaultRequestTimeout = 2 * time .Second
23+
2024// JWTGenerator interface for JWT token creation
2125type JWTGenerator interface {
2226 CreateJWTForRequest (req any ) (string , error )
@@ -35,20 +39,23 @@ type Config struct {
3539 WorkflowRegistryChainSelector uint64
3640 JWTGenerator JWTGenerator
3741
42+ RequestTimeout time.Duration // bounds each Get() call; zero means defaultRequestTimeout
43+
3844 Client linkingclient.LinkingServiceClient // optional
3945 Meter metric.Meter // optional
4046}
4147
4248// orgResolver makes direct calls to the linking service to resolve organization IDs from workflow owners.
43- // This simplified implementation makes a network call for each Get() request.
49+ // This simplified implementation makes a network call for each Get() request, bounded by requestTimeout .
4450type orgResolver struct {
4551 workflowRegistryAddress string
4652 workflowRegistryChainSelector uint64
4753
48- client linkingclient.LinkingServiceClient
49- conn * grpc.ClientConn // nil if client was injected
50- logger log.SugaredLogger
51- jwtGenerator JWTGenerator
54+ client linkingclient.LinkingServiceClient
55+ conn * grpc.ClientConn // nil if client was injected
56+ logger log.SugaredLogger
57+ jwtGenerator JWTGenerator
58+ requestTimeout time.Duration
5259
5360 passCount metric.Int64Counter
5461 failCount metric.Int64Counter
@@ -72,11 +79,17 @@ func NewOrgResolverWithClient(cfg Config, client linkingclient.LinkingServiceCli
7279}
7380
7481func (cfg * Config ) New (logger log.Logger ) (* orgResolver , error ) {
82+ requestTimeout := cfg .RequestTimeout
83+ if requestTimeout <= 0 {
84+ requestTimeout = defaultRequestTimeout
85+ }
86+
7587 resolver := & orgResolver {
7688 workflowRegistryAddress : cfg .WorkflowRegistryAddress ,
7789 workflowRegistryChainSelector : cfg .WorkflowRegistryChainSelector ,
7890 logger : log .Sugared (logger ).Named ("OrgResolver" ),
7991 jwtGenerator : cfg .JWTGenerator ,
92+ requestTimeout : requestTimeout ,
8093 }
8194
8295 if cfg .Client != nil {
@@ -135,6 +148,9 @@ func (o *orgResolver) addJWTAuth(ctx context.Context, req any) (context.Context,
135148}
136149
137150func (o * orgResolver ) Get (ctx context.Context , owner string ) (string , error ) {
151+ ctx , cancel := context .WithTimeout (ctx , o .requestTimeout )
152+ defer cancel ()
153+
138154 req := & linkingclient.GetOrganizationFromWorkflowOwnerRequest {
139155 WorkflowOwner : owner ,
140156 WorkflowRegistryAddress : o .workflowRegistryAddress ,
0 commit comments