gpoll

package module
v0.0.0-...-2397190 Latest Latest
Warning

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

Go to latest
Published: Jul 9, 2015 License: GPL-3.0 Imports: 9 Imported by: 0

README

gpoll

Long-polling server package for Go. Meant to be generic enough to work with any server generated with go. Features automated client management and coroutine (goroutine) generation and termination based on default or custom settings so you can optimize your long-polling application.

Documentation

GoDoc available at http://godoc.org/github.com/corvuscrypto/gpoll

A basic example of starting a server is:

package main

import  (
        "github.com/corvuscrypto/gpoll"
        "net/http"
        )

func HandleMessage(w http.ResponseWriter, r *http.Request) {

        /* code to detect message and do other stuff as 
           you please with the request. */
           
        var msg string = "blah blah blah"
           
        gpoll.Send(msg) //send the message string
        
        w.WriteHeader(200)
        
}

func main(){

        gpoll.ListenAndBroadcast("/path/to/listen/on")
        http.HandleFunc("/send", HandleMessage)
        http.ListenAndServe(":8080",nil)

}

And it's as easy as that!!

The ONE rule

If you are using this package, the one rule that keeps this server ticking is that you must keep track of the uuid the server sends back after initializing the polling connection. This is actually not a bad thing since in most cases it is good to track your clients anonymously, but before allowing the poll to go through properly the gpoll package always expects a query with at least the following query: ?client-id=x$xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Why?

The gpoll package uses this to maintain its routines and retrieve the proper channels to listen for messages. If you send an improper id, then you will receive an Error 404 response. To initiate a client properly so the server returns a uuid to use for subsequent polls, send the following query: ?client-id=0

if you're into the specifics...

the identifier before the $ points to the goroutine that is tracking that client. The stuff after the $ is the actual client ID.

Features

  • Automated client UUID (v4) generation
  • Automated goroutine generation and termination as needed
  • Optional Customization of the broadcasting server
  • Easy to link to any TCP server already in place
    • includes TLS servers.
  • Benchmarking suite (separate from the go test -bench suite) for fine tuning performance to fit your machine.
  • Other stuff, like buffers to prevent your clients from missing notifications, so you can spend less time making the server, and more time on developing your APIs and front-end.

Documentation

Overview

Package gpoll manages long-polling. Long-polling is a means of near-realtime data transfer that utilizes keep-alive requests to allow clients to receive data as it becomes available. Notable uses for long-polling include push notification and chat clients.

This package has the aim of making message distribution as quick as possible. The way this is accomplished in gpoll is by utilizing coroutines (goroutines) and tracking them so that coroutines are automatically created and terminated as necessary based on the number of clients connected and your configuration.

Getting Started

To use gpoll, you first need to setup a Broadcaster object. The Broadcaster object has several fields you can tweak to tune the behavior of the Broadcaster. For instance, the ClientBufferSize dictates how many massages you will allow each client buffer to store. However, because client removal is automated, the package will sense when a buffer is full, then remove that client since the program assumes this means the client is no longer listening.

If you wish to just drop in the package and use it right away, you can just have the server use the DefaultBroadcaster. This is already available and by calling the ListenAndBroadcast() function in the global context, your server will default to this object and you're ready to go. An example of such a setup is:

package main

import  (
        "github.com/corvuscrypto/gpoll"
        "net/http"
        )

func HandleMessage(w http.ResponseWriter, r *http.Request) {

        // code to detect message and do other stuff as
        // you please with the request.

        var msg string = "blah blah blah"

        gpoll.Send(msg) //send the message string

        w.WriteHeader(200)

}

func main(){

        gpoll.ListenAndBroadcast("/path/to/listen/on")
        http.HandleFunc("/send", HandleMessage)
        http.ListenAndServe(":8080",nil)

}

It's as easy as that.

Tricks

Total reset. Okay this is probably something that should never be done unless absolutely necessary, but if you need to do a full reset and kick all your users, just call the CleanUp() function. Since the CleanUp function takes an argument in the form of an int slice made up of the INDICES (not IDs) of the goroutines present within a Broadcaster, just pass in a slice containing all indices of the Broadcaster.Routines slice. This would look like this:

var resetSlice []int
for i,_ := range Broadcaster.Routines {
  resetSlice = append(resetSlice, i)
}
Broadcaster.CleanUp(resetSlice)

I'll add in support for individual client removal, but you can even implement your own client removal since the number before the '$' in a client ID is the goroutine ID. Just search the Routine object that contains that ID for your client within the Clients slice and remove it.

Index

Constants

This section is empty.

Variables

View Source
var DefaultBroadcaster = NewBroadcaster()

Functions

func ListenAndBroadcast

func ListenAndBroadcast(path string, srv ...*http.ServeMux)

ListenAndBroadcast uses the DefaultBroadcaster to set up a handler for polling requests. If supplied with a ServeMux object, it will add the handler to it, otherwise it defaults to using the DefaultServeMux object.

func Send

func Send(msg string)

Send uses the DefaultBroadcaster object to send a message to all registered clients.

func UUID

func UUID() string

UUID generator. I can't take credit for this as it was obtained from a golang-nuts discussion board (https://groups.google.com/forum/#!msg/golang-nuts/d0nF_k4dSx4/rPGgfXv6QCoJ). Acknowledgements to Russ Cox for the code and for saving me time from reading through the official UUID documentation.

Types

type Broadcaster

type Broadcaster struct {

	// Number of clients per routine
	RoutineMaxClients int

	// Maximum number of messages per client channel
	ClientBufferSize int

	// Maximum number of messages to hold in each routine's buffer
	RoutineBufferSize int

	// Number of milliseconds to wait before broadcasting message in master buffer
	// default is 0, but can be set to compensate for the time it takes for
	// clients to reconnect to the polling service.
	SyncDelayMs int

	// Routines holds routine references within the Broadcaster to allow proper
	// message handling and client maintenance.
	Routines []Routine

	// WG is a WaitGroup for ensuring synchronicity when necessary
	WG sync.WaitGroup

	// Mux is a mutex for maintaining proper data control and preventing race
	// conditions during asynchronous broadcasting and client management.
	Mux sync.Mutex

	// IsBenchmarking is used for controlling benchmark behavior
	IsBenchmarking bool

	// BenchData is an array for holding data during benchmarking. This will
	// always be cleared after benchmarking to save memory.
	BenchData []TestStruct

	// Command salt. This will automatically be generated. You can generate one
	// if you like, but make sure it is not publicly known.
	CSalt string
}

The Broadcaster struct contains configuration information to dictate long-polling behavior. The only parameters you have to assign values to are RoutineMaxClients, ClientBufferSize, and RoutineBufferSize

func NewBroadcaster

func NewBroadcaster() *Broadcaster

NewBroadcaster returns a pointer to a Broadcaster with the default settings of RoutineMaxClients: 1000, ClientBufferSize: 100, RoutineBufferSize: 200, and SyncDelayMs: 0.

func (*Broadcaster) AddClient

func (b *Broadcaster) AddClient() (string, int)

AddClient adds a client to the associated Broadcaster and returns the client ID and the routine id that manages the client.

func (*Broadcaster) Benchmark

func (b *Broadcaster) Benchmark(msgSize int, clients int, numMsgs int) error

Benchmark registers virtual clients and tests the server by sending messages of size 'msgSize' to all of them. The data is collected automatically and some basic statistics are output. This only looks at time, but may look at memory usage in the future.

func (*Broadcaster) CleanUp

func (b *Broadcaster) CleanUp(toClean []int)

CleanUp is used to terminate routines by the IDs specified in the supplied toClean parameter. This can also be used directly to shut a routine down if necessary, or trigger a full purge.

func (*Broadcaster) GetChannel

func (b *Broadcaster) GetChannel(cid string, rid int) (chan string, error)

GetChannel retrieves the reference to the receiving channel for a client based on the supplied client id ('cid') and the routine id ('rid').

func (*Broadcaster) HandleMessage

func (b *Broadcaster) HandleMessage(ch <-chan string, in int)

HandleMessage is the basis of all coroutines within the gpoll package. It contains the code that automatically manages client removal and broadcasting. Look at the source to figure out more about this function.

func (*Broadcaster) HandleRequests

func (b *Broadcaster) HandleRequests(w http.ResponseWriter, r *http.Request)

HandleRequests takes a typical http request and returns a new client ID if the client wasn't previously registered, or a broadcasted message if the client is registered.

func (*Broadcaster) ListenAndBroadcast

func (b *Broadcaster) ListenAndBroadcast(path string, srv ...*http.ServeMux)

ListenAndBroadcast uses the associated Broadcaster object to set up a handler for polling requests. If supplied with a ServeMux object, it will add the handler to it, otherwise it defaults to using the DefaultServeMux object.

func (*Broadcaster) Send

func (b *Broadcaster) Send(msg string)

Send uses the associated Broadcster object to send a message to all registered clients

type Client

type Client struct {
	//ID is the UUID of the client.
	ID string

	//Pipe is the receiving channel of the client.
	Pipe chan string
}

The Client struct holds the client id, and the channel reference for that client.

type Routine

type Routine struct {
	sync.Mutex

	// Id of the routine. This is generated automatically.
	ID int

	// Pipe holds the reference for the receiving channel of the routine.
	Pipe chan string

	// Clients holds a collection of Client objects for tracking and management.
	Clients []Client
}

The Routine struct holds information about routines, as well as the the references to clients.

type TestStruct

type TestStruct struct {

	// Ns is the time taken to complete a single broadcast in nanoseconds.
	Ns int64

	// Clients represents the number of total clients being broadcasted to.
	Clients int

	// Routines represents the total number of routines being managed by the server.
	Routines int
}

TestStruct holds benchmarking information for tuning your server.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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