Skip to content

Commit

Permalink
Merge pull request #36 from celestiaorg/mojtaba/sdk-error-enhancement
Browse files Browse the repository at this point in the history
feat: add a more precise error handling to the SDK
  • Loading branch information
mojtaba-esk authored Dec 8, 2023
2 parents 7ca1d84 + 7eefb22 commit e944605
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 50 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,5 @@
# Go workspace file
go.work
bin/
*.o
run.sh
.vscode/
4 changes: 2 additions & 2 deletions api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import (
"go.uber.org/zap"
)

const baseUrl = "/api/v1"
const EndpointPrefix = "/api/v1"

func path(endpoint string) string {
return baseUrl + endpoint
return EndpointPrefix + endpoint
}

func NewRESTApiV1(productionMode bool, logger *zap.Logger) *RESTApiV1 {
Expand Down
20 changes: 4 additions & 16 deletions api/v1/net_services_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,7 @@ import (
)

func netServiceStart(resp http.ResponseWriter, ns *netRestrictService, ifaceName string) error {
if ns == nil || ns.service == nil {
sendJSONError(resp, MetaMessage{
Type: APIMetaMessageTypeError,
Slug: SlugServiceNotInitialized,
Title: "Service not initiated",
Message: "To get the status of the service, it must be started first.",
}, http.StatusOK)
if !ensureServiceInitialized(resp, ns) {
return ErrServiceNotInitialized
}

Expand Down Expand Up @@ -43,13 +37,7 @@ func netServiceStart(resp http.ResponseWriter, ns *netRestrictService, ifaceName
}

func netServiceStop(resp http.ResponseWriter, ns *netRestrictService) error {
if ns == nil || ns.service == nil {
sendJSONError(resp, MetaMessage{
Type: APIMetaMessageTypeError,
Slug: SlugServiceNotInitialized,
Title: "Service not initiated",
Message: "To get the status of the service, it must be started first.",
}, http.StatusOK)
if !ensureServiceInitialized(resp, ns) {
return ErrServiceNotInitialized
}

Expand Down Expand Up @@ -104,7 +92,7 @@ func netServiceStatus(resp http.ResponseWriter, ns *netRestrictService) error {
Slug: SlugServiceNotInitialized,
Title: "Service not initiated",
Message: "To get the status of the service, it must be started first.",
}, http.StatusOK)
}, http.StatusInternalServerError)
return ErrServiceNotInitialized
}

Expand All @@ -125,7 +113,7 @@ func netServiceStatus(resp http.ResponseWriter, ns *netRestrictService) error {
}

func ensureServiceInitialized(resp http.ResponseWriter, ns *netRestrictService) bool {
if ns != nil {
if ns != nil && ns.service != nil {
return true
}
sendJSONError(resp,
Expand Down
35 changes: 17 additions & 18 deletions sdk/apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,60 +6,59 @@ import (
"github.com/celestiaorg/bittwister/api/v1"
)

const endpointPrefix = api.EndpointPrefix

type PacketLossStartRequest = api.PacketLossStartRequest
type BandwidthStartRequest = api.BandwidthStartRequest
type LatencyStartRequest = api.LatencyStartRequest
type ServiceStatus = api.ServiceStatus
type MetaMessage = api.MetaMessage

func (c *Client) PacketlossStart(req PacketLossStartRequest) error {
_, err := c.postResource("/packetloss/start", req)
return err
return c.postServiceAction(endpointPrefix+"/packetloss/start", req)
}

func (c *Client) PacketlossStop() error {
_, err := c.postResource("/packetloss/stop", nil)
return err
return c.postServiceAction(endpointPrefix+"/packetloss/stop", nil)
}

func (c *Client) PacketlossStatus() (*MetaMessage, error) {
return c.getServiceStatus("/packetloss/status")
return c.getServiceStatus(endpointPrefix + "/packetloss/status")
}

func (c *Client) BandwidthStart(req BandwidthStartRequest) error {
_, err := c.postResource("/bandwidth/start", req)
return err
return c.postServiceAction(endpointPrefix+"/bandwidth/start", req)
}

func (c *Client) BandwidthStop() error {
_, err := c.postResource("/bandwidth/stop", nil)
return err
return c.postServiceAction(endpointPrefix+"/bandwidth/stop", nil)
}

func (c *Client) BandwidthStatus() (*MetaMessage, error) {
return c.getServiceStatus("/bandwidth/status")
return c.getServiceStatus(endpointPrefix + "/bandwidth/status")
}

func (c *Client) LatencyStart(req LatencyStartRequest) error {
_, err := c.postResource("/latency/start", req)
return err
return c.postServiceAction(endpointPrefix+"/latency/start", req)
}

func (c *Client) LatencyStop() error {
_, err := c.postResource("/latency/stop", nil)
return err
return c.postServiceAction(endpointPrefix+"/latency/stop", nil)
}

func (c *Client) LatencyStatus() (*MetaMessage, error) {
return c.getServiceStatus("/latency/status")
return c.getServiceStatus(endpointPrefix + "/latency/status")
}

func (c *Client) AllServicesStatus() ([]ServiceStatus, error) {
resp, err := c.getResource("/services/status")
msgs := []api.ServiceStatus{}
resp, err := c.getResource(endpointPrefix + "/services/status")
if err != nil {
return nil, err
}

msgs := []api.ServiceStatus{}
if err := json.Unmarshal(resp, &msgs); err != nil {
return nil, err
}
return msgs, err
return msgs, nil
}
41 changes: 30 additions & 11 deletions sdk/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,17 @@ func (c *Client) getResource(resPath string) ([]byte, error) {
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status: %d", resp.StatusCode)
}

body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

return body, nil
var statusErr error
if resp.StatusCode != http.StatusOK {
statusErr = fmt.Errorf("unexpected status: %d", resp.StatusCode)
}

return body, statusErr
}

func (c *Client) postResource(resPath string, requestBody interface{}) ([]byte, error) {
Expand All @@ -59,27 +60,45 @@ func (c *Client) postResource(resPath string, requestBody interface{}) ([]byte,
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
return nil, fmt.Errorf("unexpected status: %d", resp.StatusCode)
}

body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

return body, nil
var statusErr error
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
statusErr = fmt.Errorf("unexpected status: %d", resp.StatusCode)
}

return body, statusErr
}

func (c *Client) getServiceStatus(resPath string) (*api.MetaMessage, error) {
resp, err := c.getResource(resPath)
if err != nil {
return nil, err
}
msg := &api.MetaMessage{}

msg := &api.MetaMessage{}
if err := json.Unmarshal(resp, msg); err != nil {
return nil, err
}
return msg, nil
}

func (c *Client) postServiceAction(resPath string, req interface{}) error {
resp, err := c.postResource(resPath, req)
if err == nil {
return nil
}

if len(resp) == 0 {
return fmt.Errorf("postResource: %w", err)
}

msg := api.MetaMessage{}
if err := json.Unmarshal(resp, &msg); err != nil {
return fmt.Errorf("raw output: %s", string(resp))
}
return Error{Message: msg}
}
65 changes: 65 additions & 0 deletions sdk/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package sdk

import (
"encoding/json"

"github.com/celestiaorg/bittwister/api/v1"
)

type Error struct {
Message MetaMessage
}

// Error returns the error message as a string
func (e Error) Error() string {
errJSON, _ := json.MarshalIndent(e.Message, "", " ")
return string(errJSON)
}

func IsErrorServiceNotInitialized(err error) bool {
e, ok := err.(Error)
if !ok {
return false
}
return e.Message.Slug == api.SlugServiceNotInitialized
}

func IsErrorServiceAlreadyStarted(err error) bool {
e, ok := err.(Error)
if !ok {
return false
}
return e.Message.Slug == api.SlugServiceAlreadyStarted
}

func IsErrorServiceNotStarted(err error) bool {
e, ok := err.(Error)
if !ok {
return false
}
return e.Message.Slug == api.SlugServiceNotStarted
}

func IsErrorServiceStopFailed(err error) bool {
e, ok := err.(Error)
if !ok {
return false
}
return e.Message.Slug == api.SlugServiceStopFailed
}

func IsErrorServiceStartFailed(err error) bool {
e, ok := err.(Error)
if !ok {
return false
}
return e.Message.Slug == api.SlugServiceStartFailed
}

func IsErrorServiceNotReady(err error) bool {
e, ok := err.(Error)
if !ok {
return false
}
return e.Message.Slug == api.SlugServiceNotReady
}
4 changes: 2 additions & 2 deletions sdk/sdk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func Test_SDK_Client_GetResource_HTTPError(t *testing.T) {

client := NewClient(mockServer.URL)
res, err := client.getResource("/error")
assert.Nil(t, res)
assert.Empty(t, res)
assert.Error(t, err)
}

Expand Down Expand Up @@ -113,7 +113,7 @@ func Test_SDK_Client_PostResource_HTTPError(t *testing.T) {
client := NewClient(mockServer.URL)
res, err := client.postResource("/error", nil)

assert.Nil(t, res)
assert.Empty(t, res)
assert.Error(t, err)
}
}
Expand Down
Binary file added xdp/bpf_bpfeb.o
Binary file not shown.
Binary file added xdp/bpf_bpfel.o
Binary file not shown.

0 comments on commit e944605

Please sign in to comment.