Skip to content

Commit

Permalink
feat(core): add post message func
Browse files Browse the repository at this point in the history
  • Loading branch information
shivanshkc committed Jul 24, 2022
1 parent 1f5efba commit a8b824c
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 6 deletions.
4 changes: 0 additions & 4 deletions src/core/constants/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,4 @@ const (
const (
// CodeOK is the success code for all scenarios.
CodeOK = "OK"
// CodeOffline is the failure code for offline clients.
CodeOffline = "OFFLINE"
// CodeBridgeNotFound is the failure code when the intended bridge cannot be located.
CodeBridgeNotFound = "BRIDGE_NOT_FOUND"
)
81 changes: 80 additions & 1 deletion src/core/func_post_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,91 @@ package core
import (
"context"

"github.com/shivanshkc/rosenbridge/src/core/constants"
"github.com/shivanshkc/rosenbridge/src/core/deps"
"github.com/shivanshkc/rosenbridge/src/core/models"
"github.com/shivanshkc/rosenbridge/src/utils/errutils"
)

// PostMessage sends a new message to the specified receivers on the behalf of the specified client.
//
// It provides detailed information on success/failure of message deliveries for every bridge.
func PostMessage(ctx context.Context, params *models.OutgoingMessageReq) (*models.OutgoingMessageRes, error) {
panic("implement me")
// Dependencies.
resolver, intercom := deps.DepManager.GetDiscoveryAddressResolver(), deps.DepManager.GetIntercom()
// Getting own discovery address.
ownAddr := resolver.Read()

// Filling empty node-addresses.
params.Bridges = expandWithNodeAddr(params.Bridges)

// Getting the request map.
requestMap := getClusterRequestMap(params)
// This channel will hold the cluster call results.
clusterCallDataChan := make(chan *clusterCallData, len(requestMap))
// Channel will be closed upon function return.
defer close(clusterCallDataChan)

// Looping over the request map to send the requests.
for nodeAddr, req := range requestMap {
var res *models.OutgoingMessageInternalRes
var err error // nolint:wsl // Declaration cuddling makes sense here.

go func(nodeAddr string, req *models.OutgoingMessageInternalReq) {
switch nodeAddr {
// This means that the client has no bridges, or the required bridge could not be found.
case "":
err = errutils.BridgeNotFound()
// If the node address is this node's own address, we call the local function.
case ownAddr:
res, err = PostMessageInternal(ctx, req)
// Otherwise, we call the remote function.
default:
res, err = intercom.PostMessageInternal(ctx, nodeAddr, req)
}

// Sending the call results to the channel.
clusterCallDataChan <- &clusterCallData{req: req, res: res, err: err}
}(nodeAddr, req)
}

// We will collect the elements of the clusterCallDataChan in this slice.
clusterCallDataSlice := make([]*clusterCallData, len(requestMap))
for i := 0; i < len(requestMap); i++ {
clusterCallDataSlice[i] = <-clusterCallDataChan
}

// Generating bridge statuses from the cluster invocation response.
bridgeStatuses := getBridgeStatuses(clusterCallDataSlice)

// The final response.
return &models.OutgoingMessageRes{
CodeAndReason: &models.CodeAndReason{Code: constants.CodeOK},
Bridges: bridgeStatuses,
}, nil
}

// expandWithNodeAddr loops through the provided bridges and populates any empty NodeAddr fields.
//
// If a record contains only client ID, it may be possible that the client has multiple bridges across multiple nodes.
// In that case, all their bridges are added in the resulting slice. Hence, this function is called expandWithNodeAddr.
func expandWithNodeAddr(bridges []*models.BridgeInfo) []*models.BridgeInfo {
return nil
}

// getClusterRequestMap generates a map of node-address to their corresponding internal request.
func getClusterRequestMap(outMessageReq *models.OutgoingMessageReq) map[string]*models.OutgoingMessageInternalReq {
return nil
}

// getBridgeStatuses generates bridge statuses from the provided cluster call data.
func getBridgeStatuses(callData []*clusterCallData) []*models.BridgeStatus {
return nil
}

// clusterCallData holds the request, response and error data points for a cluster node call.
type clusterCallData struct {
req *models.OutgoingMessageInternalReq
res *models.OutgoingMessageInternalRes
err error
}
2 changes: 1 addition & 1 deletion src/handlers/handler_get_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func GetBridge(w http.ResponseWriter, r *http.Request) { // nolint:varnamelen //
// nolint:funlen // Validation error handling makes this function larger. Making it short would be too much work!
func bridgeMessageHandler(ctx context.Context, bridge deps.Bridge, clientID string, message *models.BridgeMessage) {
// Prerequisites.
log := logger.Get() // nolint:staticcheck // Wrongly reported.
log := logger.Get()

// Obtaining request ID safely.
var requestID string
Expand Down
5 changes: 5 additions & 0 deletions src/utils/errutils/instances_custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import (
"net/http"
)

// BridgeNotFound is returned when the required bridge does not exist.
func BridgeNotFound() *HTTPError {
return &HTTPError{Status: http.StatusNotFound, Code: "BRIDGE_NOT_FOUND"}
}

// TooManyBridges is returned when there's a new bridge creation attempt but the node has reached its bridge limit.
func TooManyBridges() *HTTPError {
return &HTTPError{Status: http.StatusServiceUnavailable, Code: "TOO_MANY_BRIDGES"}
Expand Down

0 comments on commit a8b824c

Please sign in to comment.