Giter VIP home page Giter VIP logo

synse-client-go's People

Stargazers

 avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

synse-client-go's Issues

Have different constructors for clients

As @edaniszewski suggested in #1, it's a good idea to have different constructors for clients since it gives us more flexibility, like so:

// Creates a new synse client, does not specify API version.
func NewSynseClient() (*Client, error)

// Creates a new synse client with API v3
func NewSynseV3Client() (*Client, error)

cleanup: revisit implementation for streamed readings

WebSocket streamed reads have been added, but the initial implementation, while functional, feels a bit messy. This issue is to eventually go back and revisit the implementation to see if it can be cleaned up, both from a user experience perspective and from an implementation perspective.

should there be separate clients for websocket v http

In #3, its proposed that we could specify websocket v. http in a config option to the SynseClient.

A question I have is whether is make sense to do it this way, or if the semantics/usage of websockets are different enough from http to just make it its own client, e.g. related to #7

  • NewHTTPClient
  • NewHTTPClientV3
  • NewWebsocketClient
  • NewWebsocketClientV3

I'm not sure which makes the most sense, but I imagine that with a bit of research and some experimentation, it should become evident quickly

find another place for mock json responses

As of now, mock json responses are inline with their corresponding test functions. This is totally fine. However, these mock responses are very big sometimes and that make the test functions really long. If we can put them somewhere, ideally in test files, under a test data folder, that would be awesome.

check if websocket is connected prior to sending close message

func (c *websocketClient) Close() error {
// FIXME (etd): I think this will panic if close is called before connect.
err := c.connection.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
return errors.Wrap(err, "failed to close the connection gracefully")
}
return nil
}

Before we try to send a close message, check that the WebSocket connection was started, otherwise calling Close will likely lead to a panic

inconsistent annotations on scheme structs

some command options do not have annotations

// ScanOptions describes the query parameters for `/scan` endpoint.
type ScanOptions struct {
NS string
Tags []string
Force bool
Sort []string
}

while other do

// TagsOptions describes the query parameters for `/tags` endpoint.
type TagsOptions struct {
NS []string `json:"ns" mapstructure:"ns"`
IDs bool `json:"ids" mapstructure:"ids"`
}

and some have a subset of what the others have (e.g. missing mapstructure annotation)

// ReadOptions describes the query parameters for `/read` endpoint.
type ReadOptions struct {
NS string `json:"ns"`
Tags []string `json:"tags"`
}

This issue is to normalize the annotations on command options. I'm fine with there being all annotations, some, or none -- whatever makes the most sense for them. Whichever way, I think they should just be consistent.

should ReadCache return data via a channel?

I think the answer to this may be yes. Since reading cached readings may return a lot of readings at once, that would be pretty large to put into memory all at once ([]Reading) just to iterate over one at time to process.

I'm not sure of the feasibility of this, but I suspect it should be doable. Maybe changing the interface to something like

ReadCache(chan<- *scheme.Read, scheme.ReadCacheOptions) error

fix ci falling on test

in #70, according to @edaniszewski, ci has such failure on test:

+ CGO_ENABLED=0 go test -covermode=atomic ./...
go: disabling cache (/.cache/go-build) due to initialization failure: mkdir /.cache: permission denied
go: cannot use modules with build cache disabled
script returned exit code 1

@lazypower said it could be related to user permissions when using docker on host.

make sure data schemes are correct

in looking through the models, I noticed one thing that seems incorrect:

// Info describes a response from `/info` endpoint.
type Info struct {
Timestamp string `json:"timestamp" mapstructure:"timestamp"`
ID string `json:"id" mapstructure:"id"`
Type string `json:"type" mapstructure:"type"`
Metadata MetadataOptions `json:"metadata" mapstructure:"metadata"`
Plugin string `json:"plugin" mapstructure:"plugin"`
Info string `json:"info" mapstructure:"info"`
Tags []string `json:"tags" mapstructure:"tags"`
Capabilities CapabilitiesOptions `json:"capabilities" mapstructure:"capabilities"`
Output []OutputOptions `json:"output" mapstructure:"output"`
}
// MetadataOptions holds the metadata info.
type MetadataOptions struct {
Model string `json:"model" mapstructure:"model"`
}

in particular, the metadata should be a map[string]string, not its own type with expected fields -- the data in there is totally arbitrary.

I didn't notice anything else, but I'll take another pass through later and see if I notice anything.


work items for this issue:

add yaml annotations for consistent output formatting

while doing dev work for synse v3 in the synse-cli, I noticed that in some cases, yaml formatting can be different than json formatting, e.g. (see the version section):

JSON

[
  {
    "active": true,
    "id": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
    "name": "emulator plugin",
    "description": "A plugin with emulated devices and data",
    "maintainer": "vaporio",
    "tag": "vaporio/emulator-plugin",
    "vcs": "",
    "version": {
      "plugin_version": "",
      "sdk_version": "",
      "build_date": "",
      "git_commit": "",
      "git_tag": "",
      "arch": "",
      "os": ""
    }
  }
]

YAML

- active: true
  id: 4032ffbe-80db-5aa5-b794-f35c88dff85c
  name: emulator plugin
  description: A plugin with emulated devices and data
  maintainer: vaporio
  tag: vaporio/emulator-plugin
  vcs: ""
  version:
    pluginversion: ""
    sdkversion: ""
    builddate: ""
    gitcommit: ""
    gittag: ""
    arch: ""
    os: ""

This issue is to add annotations to the scheme types so yaml output will have the same keys as json output

500 responses from synse server's websocket integration tests

Follow-up on #79, below are the logs for Synse Server 500 responses for websocket requests:

scan

synse-server    | timestamp='2019-09-05T02:52:19.720950Z' level='debug' event='processing websocket request' handler='handle_request_scan'
synse-server    | timestamp='2019-09-05T02:52:19.721196Z' level='error' event='error processing request' err=TypeError("object of type 'NoneType' has no len()",)
synse-server    | timestamp='2019-09-05T02:52:19.729562Z' level='debug' event='stopping message handler for websocket' host=None

tags

synse-server    | timestamp='2019-09-05T02:54:35.514455Z' level='debug' event='processing websocket request' handler='handle_request_tags'
synse-server    | timestamp='2019-09-05T02:54:35.514598Z' level='error' event='error processing request' err=TypeError('tags() argument after * must be an iterable, not NoneType',)
synse-server    | timestamp='2019-09-05T02:54:35.523650Z' level='debug' event='stopping message handler for websocket' host=None

read

synse-server    | timestamp='2019-09-05T02:55:45.324884Z' level='debug' event='processing websocket request' handler='handle_request_read'
synse-server    | timestamp='2019-09-05T02:55:45.325572Z' level='error' event='error processing request' err=TypeError("object of type 'NoneType' has no len()",)
synse-server    | timestamp='2019-09-05T02:55:45.341372Z' level='debug' event='stopping message handler for websocket' host=None

write async

synse-server    | timestamp='2019-09-05T02:56:58.861106Z' level='debug' event='caching transaction' plugin='4032ffbe-80db-5aa5-b794-f35c88dff85c' id='eea7a761-ef56-4a86-8ccd-d862da5dba05' device='f041883c-cf87-55d7-a978-3d3103836412'
synse-server    | timestamp='2019-09-05T02:56:58.862166Z' level='debug' event='caching transaction' plugin='4032ffbe-80db-5aa5-b794-f35c88dff85c' id='f1b803a0-e7b4-441b-b4f5-04bdef14712a' device='f041883c-cf87-55d7-a978-3d3103836412'
synse-server    | timestamp='2019-09-05T02:56:58.863292Z' level='error' event='error processing request' err=TypeError("Object of type 'bytes' is not JSON serializable",)
synse-server    | timestamp='2019-09-05T02:56:58.875558Z' level='debug' event='stopping message handler for websocket' host=None

write sync

synse-server    | timestamp='2019-09-05T02:59:18.471559Z' level='debug' event='caching transaction' plugin='4032ffbe-80db-5aa5-b794-f35c88dff85c' id='dc692e5a-5ed7-46db-ba01-b2ddfc05f984' device='f041883c-cf87-55d7-a978-3d3103836412'
synse-server    | timestamp='2019-09-05T02:59:18.473183Z' level='debug' event='caching transaction' plugin='4032ffbe-80db-5aa5-b794-f35c88dff85c' id='7a14867d-37fc-4565-87e1-de1afadbf61b' device='f041883c-cf87-55d7-a978-3d3103836412'
synse-server    | timestamp='2019-09-05T02:59:18.474618Z' level='error' event='error processing request' err=TypeError("Object of type 'bytes' is not JSON serializable",)
synse-server    | timestamp='2019-09-05T02:59:18.484667Z' level='debug' event='stopping message handler for websocket' host=None

@edaniszewski, let me know if that makes sense.

Should we keep a Client interface that all clients (http, websocket) should implement?

For the most part, a Websocket and a HTTP client expose similar sets of API methods. However, since they are different in their usage and semantics, there are some methods that are only applicable for one and not the other. In those cases, these methods will have no effect but just be there to fulfill the interface. The question is, does it make sense anymore keep that Client interface that all client should implement anymore?

metrics scheme can be removed

I thought this was done previously, but maybe it slipped through the cracks. The metrics scheme (synse/scheme/metrics.go) doesn't define anything and isn't being used. Metrics will be exported from synse server as prometheus data, so it wouldn't make sense to have a struct for it here anyways.

Add websocket support for v3

TBA once v3 proposal is finalized. However, it’s likely that v3 will support websocket.

Information on websocket api for v3 can be found here.

Update documentation

This include:

  • Updating docstrings to be more descriptive
  • Adding links for reference if needed.
  • Filling in README and any additional docs on how to use.
  • Adding more examples of usage.

update return type for some API calls

there are a bunch of API calls which return *[]Type which I think should instead return []*Type -- this makes it easier to consume, as you don't have to deference the list pointer prior to using it, e.g.

response, err := client.Read()
if err != nil {
    return err
}

if len(*response) == 0 {
    return nil
}

for _, r := range *response {
    // do something
}

would become

response, err := client.Read()
if err != nil {
    return err
}

if len(response) == 0 {
    return nil
}

for _, r := range response {
    // do something
}

its a small/subtle difference, but does generally make things a bit easier to handle.

discuss assumptions/expectations of client versioning

#12 (comment)

In the above PR, I noticed a few places where version caching was being done. While that idea has been around for a while and in some degree makes sense and is a nice feature, I think we should discuss its usefulness here/the assumptions built in around it. I think that we may be able to simplify a bunch of that stuff, but I'd like to discuss and pick your brain first, @hoanhan101.

Should the client have a config to skip certificate check?

At the moment, what we have for TLS config options are:

// TLSOptions is the config options for TLS/SSL communication.
type TLSOptions struct {
	// CertFile and KeyFile are public/private key pair from a pair of files to
	// use when communicating with Synse Server.
	CertFile string `default:"-"`
	KeyFile  string `default:"-"`

	// Enabled specifies whethere tls is enabled.
	Enabled bool `default:"false"`

	// SkipVerify specifies whether the client can skip certificate checks.
	SkipVerify bool `default:"false"`
}

Even though SkipVerify should only be used for testing, I am not sure if it's a good idea to leave it exported/configurable like so. Also, linting doesn't like that either.

Use https

TBA once v3 proposal is finalized. One thing I know for sure at the moment is that the client library that we are using, go-resty/resty, supports basic authentication and tls configs.

Define configurable options

TBA once v3 proposal is finalized. Some configurable options are:

  • Synse Server’s address
  • Request timeout
  • Retry backoff strategy
  • Transport: http, websocket
  • TLS options

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.