-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CAPPL-20] Support per-method handlers in GatewayConnector #14367
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"chainlink": patch | ||
--- | ||
|
||
Support per-method handlers in GatewayConnector |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,7 @@ type GatewayConnector interface { | |
job.ServiceCtx | ||
network.ConnectionInitiator | ||
|
||
AddHandler(methods []string, handler GatewayConnectorHandler) error | ||
SendToGateway(ctx context.Context, gatewayId string, msg *api.Message) error | ||
} | ||
|
||
|
@@ -51,7 +52,7 @@ type gatewayConnector struct { | |
clock clockwork.Clock | ||
nodeAddress []byte | ||
signer Signer | ||
handler GatewayConnectorHandler | ||
handlers map[string]GatewayConnectorHandler | ||
gateways map[string]*gatewayState | ||
urlToId map[string]string | ||
closeWait sync.WaitGroup | ||
|
@@ -76,8 +77,8 @@ type gatewayState struct { | |
wsClient network.WebSocketClient | ||
} | ||
|
||
func NewGatewayConnector(config *ConnectorConfig, signer Signer, handler GatewayConnectorHandler, clock clockwork.Clock, lggr logger.Logger) (GatewayConnector, error) { | ||
if config == nil || signer == nil || handler == nil || clock == nil || lggr == nil { | ||
func NewGatewayConnector(config *ConnectorConfig, signer Signer, clock clockwork.Clock, lggr logger.Logger) (GatewayConnector, error) { | ||
if config == nil || signer == nil || clock == nil || lggr == nil { | ||
return nil, errors.New("nil dependency") | ||
} | ||
if len(config.DonId) == 0 || len(config.DonId) > network.HandshakeDonIdLen { | ||
|
@@ -93,7 +94,7 @@ func NewGatewayConnector(config *ConnectorConfig, signer Signer, handler Gateway | |
clock: clock, | ||
nodeAddress: addressBytes, | ||
signer: signer, | ||
handler: handler, | ||
handlers: make(map[string]GatewayConnectorHandler), | ||
shutdownCh: make(chan struct{}), | ||
lggr: lggr.Named("GatewayConnector"), | ||
} | ||
|
@@ -125,6 +126,22 @@ func NewGatewayConnector(config *ConnectorConfig, signer Signer, handler Gateway | |
return connector, nil | ||
} | ||
|
||
func (c *gatewayConnector) AddHandler(methods []string, handler GatewayConnectorHandler) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe addHandlers that takes an array? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Each capability will only add one handler (to support itself). |
||
if handler == nil { | ||
return errors.New("cannot add a nil handler") | ||
} | ||
for _, method := range methods { | ||
if _, exists := c.handlers[method]; exists { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why aren't you getting index from the range and then using that on c.handlers? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. c.handlers map is indexed by strings, not integers. Also here I only check for existence before adding later in the subsequent loop. |
||
return fmt.Errorf("handler for method %s already exists", method) | ||
} | ||
} | ||
// add all or nothing | ||
for _, method := range methods { | ||
c.handlers[method] = handler | ||
} | ||
return nil | ||
} | ||
|
||
func (c *gatewayConnector) SendToGateway(ctx context.Context, gatewayId string, msg *api.Message) error { | ||
data, err := c.codec.EncodeResponse(msg) | ||
if err != nil { | ||
|
@@ -159,7 +176,12 @@ func (c *gatewayConnector) readLoop(gatewayState *gatewayState) { | |
c.lggr.Errorw("failed to validate message signature", "id", gatewayState.config.Id, "err", err) | ||
break | ||
} | ||
c.handler.HandleGatewayMessage(ctx, gatewayState.config.Id, msg) | ||
handler, exists := c.handlers[msg.Body.Method] | ||
if !exists { | ||
c.lggr.Errorw("no handler for method", "id", gatewayState.config.Id, "method", msg.Body.Method) | ||
break | ||
} | ||
handler.HandleGatewayMessage(ctx, gatewayState.config.Id, msg) | ||
} | ||
} | ||
} | ||
|
@@ -194,9 +216,6 @@ func (c *gatewayConnector) reconnectLoop(gatewayState *gatewayState) { | |
func (c *gatewayConnector) Start(ctx context.Context) error { | ||
return c.StartOnce("GatewayConnector", func() error { | ||
c.lggr.Info("starting gateway connector") | ||
if err := c.handler.Start(ctx); err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see any tests that had to change because the Start and Close were removed. How is it tested that the all the handlers are started and stopped? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two lines were removed from connector_test.go:
|
||
return err | ||
} | ||
for _, gatewayState := range c.gateways { | ||
gatewayState := gatewayState | ||
if err := gatewayState.conn.Start(ctx); err != nil { | ||
|
@@ -214,11 +233,12 @@ func (c *gatewayConnector) Close() error { | |
return c.StopOnce("GatewayConnector", func() (err error) { | ||
c.lggr.Info("closing gateway connector") | ||
close(c.shutdownCh) | ||
var errs error | ||
for _, gatewayState := range c.gateways { | ||
gatewayState.conn.Close() | ||
errs = errors.Join(errs, gatewayState.conn.Close()) | ||
} | ||
c.closeWait.Wait() | ||
return c.handler.Close() | ||
return errs | ||
}) | ||
} | ||
|
||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not give it an array of handlers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't have them when the connector is constructed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we had a single handler before for calling the connector, why wouldn't we have one still? Is it because the service_wrapper is being created and it won't be ready at connector construction time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We had one handler ready here before only because in Functions the Connector object was created by a job spec. Now that you moved it to be a core service, it's not the case any more. Core services (now including Gateway Connector) are all created first, before iterating over job specs and creating services that they need. In the re-design proposal (see doc I shared earlier today), each standard capability will add its own connector handler, when neccesary.