Skip to content

Commit

Permalink
feat!: replace REST device validation callback with MessageBus (#1325)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: remove /validate/device REST endpoint

closes #1260

Signed-off-by: Chris Hung <chris@iotechsys.com>
  • Loading branch information
Chris Hung authored Feb 22, 2023
1 parent 5827dcb commit b7afc2a
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 211 deletions.
2 changes: 0 additions & 2 deletions internal/controller/http/restrouter.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ func (c *RestController) InitRestRoutes() {
c.addReservedRoute(common.ApiSecretRoute, c.Secret).Methods(http.MethodPost)
// discovery
c.addReservedRoute(common.ApiDiscoveryRoute, c.Discovery).Methods(http.MethodPost)
// validate
c.addReservedRoute(common.ApiDeviceValidationRoute, c.ValidateDevice).Methods(http.MethodPost)
// device command
c.addReservedRoute(common.ApiDeviceNameCommandNameRoute, c.GetCommand).Methods(http.MethodGet)
c.addReservedRoute(common.ApiDeviceNameCommandNameRoute, c.SetCommand).Methods(http.MethodPut)
Expand Down
44 changes: 0 additions & 44 deletions internal/controller/http/validation.go

This file was deleted.

122 changes: 0 additions & 122 deletions internal/controller/http/validation_test.go

This file was deleted.

4 changes: 1 addition & 3 deletions internal/controller/messaging/callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import (
"github.com/edgexfoundry/device-sdk-go/v3/internal/container"
)

const MetadataSystemEventTopic = "MetadataSystemEventTopic"

func MetadataSystemEventCallback(ctx context.Context, dic *di.Container) errors.EdgeX {
lc := bootstrapContainer.LoggingClientFrom(dic.Get)
messageBusInfo := container.ConfigurationFrom(dic.Get).MessageBus
Expand Down Expand Up @@ -57,7 +55,7 @@ func MetadataSystemEventCallback(ctx context.Context, dic *di.Container) errors.
case err = <-messageErrors:
lc.Error(err.Error())
case msgEnvelope := <-messages:
lc.Debugf("System event received on message queue. Topic: %s, Correlation-id: %s ", metadataSystemEventTopic, msgEnvelope.CorrelationID)
lc.Debugf("System event received on message queue. Topic: %s, Correlation-id: %s", msgEnvelope.ReceivedTopic, msgEnvelope.CorrelationID)

var systemEvent dtos.SystemEvent
err := json.Unmarshal(msgEnvelope.Payload, &systemEvent)
Expand Down
4 changes: 2 additions & 2 deletions internal/controller/messaging/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func SubscribeCommands(ctx context.Context, dic *di.Container) errors.EdgeX {
case err = <-messageErrors:
lc.Error(err.Error())
case msgEnvelope := <-messages:
lc.Debugf("Command request received on message queue. Topic: %s, Correlation-id: %s ", requestSubscribeTopic, msgEnvelope.CorrelationID)
lc.Debugf("Command request received on message queue. Topic: %s, Correlation-id: %s", msgEnvelope.ReceivedTopic, msgEnvelope.CorrelationID)

// expected command request topic scheme: #/<service-name>/<device-name>/<command-name>/<method>
topicLevels := strings.Split(msgEnvelope.ReceivedTopic, "/")
Expand All @@ -86,7 +86,7 @@ func SubscribeCommands(ctx context.Context, dic *di.Container) errors.EdgeX {
continue
}

lc.Debugf("Command response published on message queue. Topic: %s, Correlation-id: %s ", responsePublishTopic, msgEnvelope.CorrelationID)
lc.Debugf("Command response published on message queue. Topic: %s, Correlation-id: %s", responsePublishTopic, msgEnvelope.CorrelationID)
}
}
}()
Expand Down
106 changes: 106 additions & 0 deletions internal/controller/messaging/validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//
// Copyright (C) 2023 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

package messaging

import (
"context"
"encoding/json"

bootstrapContainer "github.com/edgexfoundry/go-mod-bootstrap/v3/bootstrap/container"
"github.com/edgexfoundry/go-mod-bootstrap/v3/di"
"github.com/edgexfoundry/go-mod-core-contracts/v3/common"
"github.com/edgexfoundry/go-mod-core-contracts/v3/dtos"
"github.com/edgexfoundry/go-mod-core-contracts/v3/dtos/requests"
"github.com/edgexfoundry/go-mod-core-contracts/v3/errors"
"github.com/edgexfoundry/go-mod-messaging/v3/pkg/types"

"github.com/edgexfoundry/device-sdk-go/v3/internal/container"
)

func SubscribeDeviceValidation(ctx context.Context, dic *di.Container) errors.EdgeX {
lc := bootstrapContainer.LoggingClientFrom(dic.Get)
messageBusInfo := container.ConfigurationFrom(dic.Get).MessageBus
serviceName := container.DeviceServiceFrom(dic.Get).Name

requestTopic := common.BuildTopic(messageBusInfo.GetBaseTopicPrefix(), serviceName, common.ValidateDeviceSubscribeTopic)
lc.Infof("Subscribing to device validation requests on topic: %s", requestTopic)

responseTopicPrefix := common.BuildTopic(messageBusInfo.GetBaseTopicPrefix(), common.ResponseTopic, serviceName)
lc.Infof("Responses to device validation requests will be published on topic: %s/<requestId>", responseTopicPrefix)

messages := make(chan types.MessageEnvelope)
messageErrors := make(chan error)
topics := []types.TopicChannel{
{
Topic: requestTopic,
Messages: messages,
},
}

messageBus := bootstrapContainer.MessagingClientFrom(dic.Get)
err := messageBus.Subscribe(topics, messageErrors)
if err != nil {
return errors.NewCommonEdgeXWrapper(err)
}

go func() {
for {
select {
case <-ctx.Done():
lc.Infof("Exiting waiting for MessageBus '%s' topic messages", requestTopic)
return
case err = <-messageErrors:
lc.Error(err.Error())
case msgEnvelope := <-messages:
lc.Debugf("Device validation request received on message queue. Topic: %s, Correlation-id: %s", msgEnvelope.ReceivedTopic, msgEnvelope.CorrelationID)

responseTopic := common.BuildTopic(responseTopicPrefix, msgEnvelope.RequestID)

validator := container.DeviceValidatorFrom(dic.Get)
if validator != nil {
var deviceRequest requests.AddDeviceRequest
err = json.Unmarshal(msgEnvelope.Payload, &deviceRequest)
if err != nil {
lc.Errorf("Failed to JSON decoding AddDeviceRequest: %s", err.Error())
res := types.NewMessageEnvelopeWithError(msgEnvelope.RequestID, err.Error())
err = messageBus.Publish(res, responseTopic)
if err != nil {
lc.Errorf("Failed to publish device validation error response: %s", err.Error())
}
continue
}

err = validator.ValidateDevice(dtos.ToDeviceModel(deviceRequest.Device))
if err != nil {
lc.Errorf("Device validation failed: %s", err.Error())
res := types.NewMessageEnvelopeWithError(msgEnvelope.RequestID, err.Error())
err = messageBus.Publish(res, responseTopic)
if err != nil {
lc.Errorf("Failed to publish device validation error response: %s", err.Error())
}
continue
}
}

res, err := types.NewMessageEnvelopeForResponse(nil, msgEnvelope.RequestID, msgEnvelope.CorrelationID, common.ContentTypeJSON)
if err != nil {
lc.Errorf("Failed to create device validation response envelope: %s", err.Error())
continue
}

err = messageBus.Publish(res, responseTopic)
if err != nil {
lc.Errorf("Failed to publish device validation response: %s", err.Error())
continue
}

lc.Debugf("Device validation response published on message queue. Topic: %s, Correlation-id: %s", responseTopic, msgEnvelope.CorrelationID)
}
}
}()

return nil
}
Loading

0 comments on commit b7afc2a

Please sign in to comment.