Documentation ¶
Overview ¶
Package asyncserver provides the framework for an async server.
This work is licensed under CC0 1.0 Universal (CC0 1.0), Public Domain Dedication. For details see:
http://creativecommons.org/publicdomain/zero/1.0/
Online go-documentation is available at:
https://godoc.org/bitbucket.org/pcas/serverutil/async/asyncserver
/////////////////////////////////////////////////////////////////////// server.go ///////////////////////////////////////////////////////////////////////
A Server listens for tasks on a specified connection and responds appropriately, with cancellation provided by a context ctx. So typical usage looks like:
ln, err := net.Listen("tcp", ":8080")
if err != nil { // handle error }
s := asyncserver.New(timeouts)
for acceptingConnections { conn, err := ln.Accept() if err != nil { // handle error } // Typically some form of client handshake code goes here; this provides an // opportunity to determine the byte order e being used by the client. // ... // Handle the connection go s.HandleConnection(ctx, conn, e) }
Here timeouts describes the *asyncserver.Timeout durations (and can be nil, in which case the default timeouts will be used), and ctx is a context.Context that can be used to terminate the client connection. Typically you will install a signal handler which, on catching a signal that indicates we should shut down, sets acceptingConnections to false and calls the cancel function for the context ctx.
Index ¶
- Constants
- Variables
- type Client
- func (c *Client) ByteOrder() binary.ByteOrder
- func (c *Client) Cancel(id async.TaskID)
- func (c *Client) CancelAll()
- func (c *Client) Close() error
- func (c *Client) Disconnect(d time.Duration)
- func (c *Client) LocalAddr() net.Addr
- func (c *Client) Log() log.Interface
- func (c *Client) Metadata(id async.TaskID) *async.TaskMetadata
- func (c *Client) Metrics() metrics.Interface
- func (c *Client) RemoteAddr() net.Addr
- func (c *Client) RunData(id async.TaskID) interface{}
- func (c *Client) Server() *Server
- func (c *Client) SetLogger(lg log.Interface)
- func (c *Client) SetMetrics(m metrics.Interface)
- func (c *Client) String() string
- func (c *Client) TaskCodes() []serverutil.TaskCode
- func (c *Client) Tasks() []async.TaskID
- func (c *Client) TasksWithTaskCode(t serverutil.TaskCode) []async.TaskID
- func (c *Client) Timestamp() time.Time
- type RunFunc
- type Server
- func (s *Server) Clients() []serverutil.Client
- func (s *Server) Disconnect(d time.Duration)
- func (s *Server) HandleConnection(ctx context.Context, conn net.Conn, e binary.ByteOrder, args ...interface{}) error
- func (s *Server) Log() log.Interface
- func (s *Server) Metrics() metrics.Interface
- func (s *Server) NumClients() (n int)
- func (s *Server) Register(t serverutil.TaskCode, f TaskFunc, name string)
- func (s *Server) RegisteredTaskCodes() []serverutil.TaskCode
- func (s *Server) SetLogger(l log.Interface)
- func (s *Server) SetMetrics(m metrics.Interface)
- func (s *Server) TaskFunc(t serverutil.TaskCode) (TaskFunc, string, bool)
- func (s *Server) Wait()
- type TaskFunc
- type Timeout
Constants ¶
const ( DefaultWait = 30 * time.Minute DefaultRead = 5 * time.Second DefaultWrite = 5 * time.Second )
The default timeout durations.
Variables ¶
var ( ErrGracefulDisconnect = errors.New("Graceful disconnection") // ErrGracefulDisconnect indicates that a graceful disconnection was used to close the client connection. ErrTimeoutWaitingForTask = errors.New("Timeout whilst waiting for task") // ErrTimeoutWaitingForTask indicates that the server timed-out whilst waiting for a new task from the client. )
Common errors.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client describes a client.
func (*Client) Cancel ¶
Cancel cancels the task with given task id. If no task is currently assigned the given id, or if the corresponding task has already been cancelled, this does nothing.
func (*Client) CancelAll ¶
func (c *Client) CancelAll()
CancelAll cancels all currently assigned tasks.
func (*Client) Disconnect ¶
Disconnect begins a graceful disconnection. It will immediately call CloseRead on the underlying connection, and schedules a future Close on the connection after duration d has elapsed. Note that there is no way to cancel a graceful disconnection once started. If Disconnect is called again, then the final Close will be performed after the shortest of the two durations has expired. This is a non-blocking method.
func (*Client) Metadata ¶
func (c *Client) Metadata(id async.TaskID) *async.TaskMetadata
Metadata returns the metadata for the given task id, or nil if no currently assigned task has this id.
func (*Client) RemoteAddr ¶
RemoteAddr returns the remote network address.
func (*Client) RunData ¶
RunData returns the run data for the given task id, or nil if no currently assigned task has this id.
func (*Client) SetLogger ¶
SetLogger sets the logger for this client. By default the logger is inherited from the server.
func (*Client) SetMetrics ¶
SetMetrics sets the metrics endpoint for this client. By default this is inherited from the server.
func (*Client) String ¶
String returns a string description of the client of the form "remote addr->local addr".
func (*Client) TaskCodes ¶
func (c *Client) TaskCodes() []serverutil.TaskCode
TaskCodes returns a slice of all assigned tasks codes. The task codes are sorted in assigned order, from oldest (at index 0) to most recent.
func (*Client) Tasks ¶
Tasks returns a slice of all assigned task ids. The ids are distinct, and sorted in increasing order.
func (*Client) TasksWithTaskCode ¶
func (c *Client) TasksWithTaskCode(t serverutil.TaskCode) []async.TaskID
TasksWithTaskCode returns a slice of all currently assigned task ids in the state with the given task code. The ids are distinct, and sorted in increasing order.
type RunFunc ¶
type RunFunc func(ctx context.Context, c *Client, id async.TaskID, lg log.Interface) (r io.Reader, err error)
RunFunc is the function that will run the task. It is the run function's responsibility to create the response data to send to a client.
Run functions are executed concurrently. Any run data returned by the originating task function can be recovered by passing the task id to the client's GetRunData method, e.g. d := c.GetRunData(id).
If no error is returned (i.e. if err == nil), then the success header
- response code serverutil.OK (1 byte)
- task ID (4 byte)
will be sent to the client, followed by the contents of the returned io.Reader r. The contents of r will be automatically encoded as per the definition of client-server communication before being sent to the client. If the copying of data from the io.Reader r to the client fails because of an error then the situation is serious: the client will be placed in an error state, and the connection will be dropped. If r satisfies the io.Closer interface then its Close() method will be called once copying stops (for whatever reason). If you do not need to send any data to the client, it is permitted for the returned io.Reader r to be nil.
If a non-nil error is returned then the reader r will be ignored. If err satisfies the serverutil.ErrorCoder interface, then
- response code serverutil.Error (1 byte)
- task ID (4 bytes)
- error code (1 byte)
will be sent to the client, where the error code is given by err.ErrorCode(). If the returned error does not satisfy the serverutil.ErrorCoder interface then the situation is serious: the client will be placed in an error state, and the connection will be dropped.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server handles async communication with clients.
func New ¶
New returns a new server. If timeout is nil then the default timeout durations will be used. This satisfies the serverutil.Server interface.
func (*Server) Clients ¶
func (s *Server) Clients() []serverutil.Client
Clients returns all client connections currently being handled by this server. The returned slice is sorted by increasing timestamp. Note: The underlying type of the entries in the returned slice is *Client.
func (*Server) Disconnect ¶
Disconnect calls the Disconnect method with duration d for each client currently being handled by this server.
func (*Server) HandleConnection ¶
func (s *Server) HandleConnection(ctx context.Context, conn net.Conn, e binary.ByteOrder, args ...interface{}) error
HandleConnection handles tasks from the given connection conn using the given byte order e. Use the given context to trigger a graceful disconnection. The connection will be closed on return. The given args will be passed to the task functions.
func (*Server) NumClients ¶
NumClients returns the number of client connections currently being handled by this server.
func (*Server) Register ¶
func (s *Server) Register(t serverutil.TaskCode, f TaskFunc, name string)
Register registers a task function for the given task code. If a function is already registered for this task code, it will be replaced with the new function. The given name is used purely for logging purposes, and will be ignored if empty. This will panic if the task code is in the reserved range.
func (*Server) RegisteredTaskCodes ¶
func (s *Server) RegisteredTaskCodes() []serverutil.TaskCode
RegisteredTaskCodes returns a slice of all currently registered task codes.
func (*Server) SetMetrics ¶
SetMetrics sets a metrics endpoint.
type TaskFunc ¶
type TaskFunc func(r binaryutil.BinaryReader, lg log.Interface, args ...interface{}) (f RunFunc, d interface{}, err error)
TaskFunc describes a task. It is the task function's responsibility to read the message data sent by a client.
The task function should do as little work as possible: only one task function per client can be executed at a time. The task function should return a run function f that will execute the task and return either the response data, or a error. If no run function needs to be called, the task function is free to return a nil-valued run function.
The task function may also return run data d. This optional data can be recovered at any time during the lifetime of the run function via the client's GetRunData method. Although typically data will be passed from the task function to the run function via a closure, it can sometimes be useful to store run-specific data in a publicly accessible way. The run data (if any) will become unavailable once the run function terminates.
If a non-nill error is returned then the run function f and run data d will be ignored. The client will be placed in an error state and the connection will be dropped. The task function should only return an error if the situation is serious.