graphqlws

package
v0.0.0-...-8dcdab8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 18, 2020 License: MIT Imports: 19 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client manages a single connection to a GraphQL web socket server, which may host any number of GraphQL queries, mutations, and subscriptions concurrently. A Client object must be intialized using the NewClient function.

func NewClient

func NewClient(ctx context.Context, config *ClientConfig) (*Client, error)

NewClient creates and connects a new GraphQL web socket client to a GraphQL web socket server.

func (*Client) Close

func (c *Client) Close() error

Close is a non-blocking function that immediately terminates the connection and cleans up resources in use by the Client.

func (*Client) Mutation

func (c *Client) Mutation(ctx context.Context, config *MutationConfig) (*GQLDataPayload, error)

Mutation performs a GraphQL mutation over the client's websocket.

func (*Client) Query

func (c *Client) Query(ctx context.Context, config *QueryConfig) (*GQLDataPayload, error)

Query performs a GraphQL query over the client's websocket.

func (*Client) Shutdown

func (c *Client) Shutdown(ctx context.Context) error

Shutdown attempts to close the client gracefully, terminating all ongoing operations correctly before closing the websocket and terminating the connection. The provided context can be used to cancel the shutdown prematurely in the event that it stalls or takes longer than is acceptable.

func (*Client) Subscription

func (c *Client) Subscription(config *SubscriptionConfig) (*Subscription, error)

Subscription registers a GraphQL subscription for repeated updates over the client's websocket.

type ClientConfig

type ClientConfig struct {

	// Logger can be used to customize the way the client logs information.
	// A nil value on this field will cause all logs to be discarded. Logs
	// are only meant to be used for troubleshooting, so this is usually the
	// desired behaviour.
	Logger Logger

	// Address defines the address component of the URL that will be used in
	// the request to connect to the server.
	Address string

	// Path defines the path component of the URL that will be used in the
	// request to connect to the server.
	Path string

	// Dialer can be used to provide the 'websocket.Dialer' that will be
	// used to connect to a server. This may be useful if the client needs
	// to be proxied or make use of a cookiejar. When left as nil, the
	// client will dial using the default dialer (websocket.DefaultDialer).
	Dialer *websocket.Dialer

	// Header can be used to provide a HTTP header that will be combined
	// with the header the client will use in its initial HTTP request.
	// This may be useful if the server handles authentication and
	// authorization via headers. For most cases it will be okay to leave
	// this as nil.
	Header http.Header

	// InitialPayload will be sent to the server during the first stages
	// initializing the connection. A GraphQL web socket server's
	// expectations regarding the initial payload can vary from
	// implementation to implementation, but it is a common requirement that
	// this payload contain information used to authenticate and authorize
	// the client.
	InitialPayload interface{}

	// ReadTimeout determines the maximum length of time a client will wait
	// in between each message received from the server. This setting only
	// comes into effect if the connected server is configured to
	// 'keep-alive' the connection. While in effect, if this interval is
	// ever exceeded the connection will be considered corrupt, causing the
	// client to close itself down. If left as zero, no read timeout will
	// be enforced.
	ReadTimeout time.Duration

	// WriteTimeout determines the maximum length of time a client will wait
	// for the server to receive each message. If this interval is ever
	// exceeded the connection will be considered corrupt, causing the
	// client to close itself down. If left as zero, no write timeout will
	// be enforced.
	WriteTimeout time.Duration
}

ClientConfig aggregates adjustable settings that can be used to modify the behaviour of the GraphQL web socket client.

type Cluster

type Cluster struct {
	// contains filtered or unexported fields
}

Cluster represents an entire cluster of Publishers working as a HA (highly-available) unit. By clustering Publishers load can be distributed across multiple machines, and implementations of the Cluster interface ensure that updates published to one node also reach subscribers to the other nodes.

func NewCluster

func NewCluster(config ClusterConfig) (*Cluster, error)

NewCluster returns a basic implementation of the Cluster interface assembled from implementations of the various critical elements of the provided ClusterConfig.

Although it notifies peers via HTTP, it does not perform any complicated logic to guarantee that all peers receive their notification. If an error occurs in an attempt to notify a peer, the error is logged and ignored.

func (*Cluster) Publish

func (c *Cluster) Publish(update Update)

Publish pushed out an update to all nodes in the cluster. It is an implementation of Publisher, making it easy to swap in and out with non-clustered Publisher implementations.

func (*Cluster) ServeHTTP

func (c *Cluster) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements 'http.Handler' and should be served on a 'http.Server' somewhere. This handler is the input exposed by the Cluster that should be contacted by other nodes in the cluster in order to trigger an update.

The handler expects a POST request with a payload containing JSON that will unmarshal into a valid Update description.

type ClusterConfig

type ClusterConfig struct {

	// Clusterable is the Clusterable object to be managed by the Cluster.
	Clusterable Clusterable

	// Logger can be used to configure the log output of the Cluster.
	Logger Logger

	// Is the Peers object that is used to communicate with the other nodes
	// of the cluster.
	Peers Peers
}

ClusterConfig contains fields used to customize the behaviour of a basic implementation of the Cluster interface.

type Clusterable

type Clusterable interface {

	// Something Clusterable must be capable of publishing updates.
	Publish(update Update)

	// Schema returns an implementation of Schema, which is used by the
	// implementation of Cluster to reconstruct Update objects that have
	// been received from peers.
	Schema() Schema
}

Clusterable is used as a part of the ClusterConfig in order to create an implementation of the Cluster interface based on any underlying Publisher.

type GQLDataPayload

type GQLDataPayload struct {
	Data   interface{} `json:"data,omitempty"`
	Errors []GQLError  `json:"errors,omitempty"`
}

GQLDataPayload is a generic structure for a response to a valid GraphQL operation.

type GQLError

type GQLError struct {
	Locations  []GQLErrorLocation     `json:"locations,omitempty"`
	Message    string                 `json:"message"`
	Path       []string               `json:"path,omitempty"`
	Extensions map[string]interface{} `json:"extensions,omitempty"`
}

GQLError contains an error description with information meant to be useful for a developer that needs to debug it.

func (*GQLError) Error

func (e *GQLError) Error() string

type GQLErrorLocation

type GQLErrorLocation struct {
	Line   int `json:"line"`
	Column int `json:"column"`
}

GQLErrorLocation contains a reference to a location in the operation's query string related to an error that has occurred.

type GQLStartPayload

type GQLStartPayload struct {
	Query         string                 `json:"query"`
	Variables     map[string]interface{} `json:"variables"`
	OperationName string                 `json:"operationName"`
}

GQLStartPayload is the structure for a GQL_START message payload.

type Logger

type Logger interface {

	// Info logs a general information message. This is verbose and should
	// be discarded except when troubleshooting.
	Info(message string)

	// Error logs a message describing a non-critical error that has
	// occurred. This is not verbose but is also for troubleshooting
	// purposes. It is okay to discard these messages because the library
	// only logs errors that can be recovered or ignored. Critical errors
	// will always be returned as an error somewhere.
	Error(message string)
}

Logger provides an interface allowing the library's internal logging to be handled by third party logging libraries.

type Message

type Message struct {
	Payload interface{} `json:"payload,omitempty"`
	ID      string      `json:"id,omitempty"`
	Type    MessageType `json:"type"`
}

Message is the generalized form for a GraphQL over websocket message.

func (*Message) GQLDataPayload

func (m *Message) GQLDataPayload() (*GQLDataPayload, error)

type MessageType

type MessageType string

MessageType is a string representing a specific type of message.

const (
	MessageTypeGQLConnectionInit      MessageType = "connection_init"
	MessageTypeGQLStart               MessageType = "start"
	MessageTypeGQLStop                MessageType = "stop"
	MessageTypeGQLConnectionTerminate MessageType = "connection_terminate"
	MessageTypeGQLConnectionError     MessageType = "connection_error"
	MessageTypeGQLConnectionAck       MessageType = "connection_ack"
	MessageTypeGQLData                MessageType = "data"
	MessageTypeGQLError               MessageType = "error"
	MessageTypeGQLComplete            MessageType = "complete"
	MessageTypeGQLConnectionKeepAlive MessageType = "ka"
)

GQL message types

type MutationConfig

type MutationConfig struct {
	Query         string                 `json:"query"`
	Variables     map[string]interface{} `json:"variables"`
	OperationName string                 `json:"operationName"`
}

MutationConfig contains fields used by the client to perform a GraphQL mutation clientOperation.

type Peer

type Peer interface {
	// Notify sends an Update to the peer.
	Notify(update Update) error
}

Peer represents another node within a cluster. It is used by implementation of Cluster to notify other nodes in the cluster that an Update has been published.

type Peers

type Peers interface {
	// Peers returns a complete list of Peer objects in the cluster.
	Peers() []Peer
}

Peers represents the collection of all peers. It exists as an interface in case the implementation wants to handle some management of the underlying peers.

type QueryConfig

type QueryConfig struct {
	Query         string                 `json:"query"`
	Variables     map[string]interface{} `json:"variables"`
	OperationName string                 `json:"operationName"`
}

QueryConfig contains fields used by the client to perform a GraphQL query clientOperation.

type Schema

type Schema interface {

	// Fields returns a list of alphabetically sorted strings representing
	// each leaf of a GraphQL schema's subscriptions.
	Fields() []string

	// NewUpdate returns an Update object created from a list of fields. All
	// fields provided should exists in the list of strings returned by the
	// Fields function on this interface.
	NewUpdate(fields ...string) Update

	// UpdateFromObject is a convenience function that will check if the
	// provided object pointer can be found anywhere in the underlying
	// schema, and use the results of this search to create a new Update
	// from all of the identified fields. The function must be smart enough
	// to find the object if it appears multiple times in the same schema.
	UpdateFromObject(o *graphql.Object) Update

	// UpdateFromJSON must be able to recreate an Update object from a JSON
	// payload (as created by the Update object's MarshalJSON function). It
	// must also be able to validate that the payload perfectly matches the
	// schema. This is necessary to prevent bugs caused by mismatched
	// GraphQL schemas that could occur when Updates are published to a
	// cluster.
	UpdateFromJSON(data []byte) (Update, error)
}

Schema contains information and methods used to analyze a GraphQL schema and generate Update objects.

func NewSchema

func NewSchema(gql graphql.Schema) Schema

NewSchema analyzes the provided 'graphql.Schema' and returns an implementation of the Schema interface.

type Server

type Server struct {
	// contains filtered or unexported fields
}

func NewServer

func NewServer(config *ServerConfig) (*Server, error)

func (*Server) Close

func (s *Server) Close() error

func (*Server) Publish

func (s *Server) Publish(update Update)

func (*Server) Schema

func (s *Server) Schema() Schema

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

type ServerConfig

type ServerConfig struct {
	Logger          Logger
	Schema          graphql.Schema
	EnableKeepAlive bool
	PollingInterval time.Duration
	ReadTimeout     time.Duration
	WriteTimeout    time.Duration
}

type SimplePeer

type SimplePeer struct {
	Client *http.Client
	Header http.Header
	URL    *url.URL
}

SimplePeer is the basic implementation of the Peer interface.

func (*SimplePeer) Notify

func (p *SimplePeer) Notify(update Update) error

Notify implements the Peer interface by sending a POST request to the SimplePeer's URL. The POST request conforms to the expectations of the Cluster's ServeHTTP handler so that the peer will trigger an update of its GraphQL Web Socket server.

type StaticPeers

type StaticPeers []Peer

StaticPeers makes a type out of a slice of Peer object so methods can be attached in order to satisfy the Peers interface.

func (StaticPeers) Peers

func (ps StaticPeers) Peers() []Peer

Peers satisfies the Peers interface.

type Subscription

type Subscription struct {
	// contains filtered or unexported fields
}

Subscription provides a handle for an active subscription with functions to terminate the subscription and to wait until the subscription has finished.

func (*Subscription) Stop

func (s *Subscription) Stop()

func (*Subscription) WaitUntilFinished

func (s *Subscription) WaitUntilFinished(ctx context.Context) error

type SubscriptionConfig

type SubscriptionConfig struct {
	Query         string
	Variables     map[string]interface{}
	OperationName string
	DataCallback  func(payload *GQLDataPayload)
	ErrorCallback func(err error)
}

SubscriptionConfig contains fields used by the client to perform a GraphQL subscription clientOperation.

type Update

type Update interface {

	// When martialled into JSON, an Update should contain enough
	// information for a Schema to completely reconstruct it and also
	// validate that it is meant for the same Schema. This is necessary to
	// prevent bugs caused by mismatched GraphQL schemas that could occur
	// when Updates are published to a cluster.
	json.Marshaler

	// Overlaps returns true if the two Update objects share at least one
	// field (or leaf) of the GraphQL schema.
	Overlaps(update Update) bool
}

Update contains information and methods used to help the server decide which subscriptions should be updated. A good implementation of Update should front-load computation because it should be considered reusable, and it is important to minimize the computational complexity of the Overlaps function.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL