Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jcuga/Golongpoll
golang long polling library. Makes web pub-sub easy via HTTP long-poll servers and clients :smiley: :coffee: :computer:
https://github.com/jcuga/Golongpoll
go golang golang-library longpoll longpoll-api longpoll-requests longpoller longpolling pubsub pubsub-publisher pubsub-subscriber
Last synced: 18 days ago
JSON representation
golang long polling library. Makes web pub-sub easy via HTTP long-poll servers and clients :smiley: :coffee: :computer:
- Host: GitHub
- URL: https://github.com/jcuga/Golongpoll
- Owner: jcuga
- License: mit
- Created: 2015-11-02T00:32:56.000Z (about 9 years ago)
- Default Branch: master
- Last Pushed: 2023-08-20T19:40:52.000Z (about 1 year ago)
- Last Synced: 2024-07-31T01:27:03.439Z (3 months ago)
- Topics: go, golang, golang-library, longpoll, longpoll-api, longpoll-requests, longpoller, longpolling, pubsub, pubsub-publisher, pubsub-subscriber
- Language: Go
- Homepage:
- Size: 320 KB
- Stars: 654
- Watchers: 23
- Forks: 60
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# golongpoll ![build workflow](https://github.com/jcuga/golongpoll/actions/workflows/main.yml/badge.svg) [![codecov](https://codecov.io/gh/jcuga/golongpoll/branch/master/graph/badge.svg)](https://codecov.io/gh/jcuga/golongpoll) [![GoDoc](https://godoc.org/github.com/jcuga/golongpoll?status.svg)](https://godoc.org/github.com/jcuga/golongpoll) [![Go Report Card](https://goreportcard.com/badge/jcuga/golongpoll)](https://goreportcard.com/report/jcuga/golongpoll)
Golang long polling library. Makes web pub-sub easy via HTTP long-poll servers and clients.## Resources
* [go docs](https://pkg.go.dev/github.com/jcuga/golongpoll)
* [examples](/examples/README.md) - shows how to use the longpoll server and go/js clients.
* [go client](/client/README.md)
* [javascript client](/js-client/README.md)
* [longpoll http api](/HttpLongPollAPI.md) - in case you want to create your own client.
* [longpoll with gin apps](#long-polling-and-gin)## QuickStart
To create a longpoll server:
```go
import (
"github.com/jcuga/golongpoll"
)// This uses the default/empty options. See section on customizing, and Options go docs.
manager, err := golongpoll.StartLongpoll(golongpoll.Options{})// Expose pub-sub. You could omit the publish handler if you don't want
// to allow clients to publish. For example, if clients only subscribe to data.
if err == nil {
http.HandleFunc("/events", manager.SubscriptionHandler)
http.HandleFunc("/publish", manager.PublishHandler)
http.ListenAndServe("127.0.0.1:8101", nil)
} else {
// handle error creating longpoll manager--typically this means a bad option.
}
```The above snippet will create a [LongpollManager](https://pkg.go.dev/github.com/jcuga/golongpoll#LongpollManager) which has a `SubscriptionHandler` and a `PublishHandler` that can served via http (or using https). When created, the manager spins up a separate goroutine that handles the plumbing for pub-sub.
`LongpollManager` also has a [Publish](https://pkg.go.dev/github.com/jcuga/golongpoll#LongpollManager.Publish) function that can be used to publish events. You can call `manager.Publish("some-category", "some data here")` and/or expose the `manager.PublishHandler` and allow publishing of events via the [longpoll http api](/HttpLongPollAPI.md). For publishing within the same program as the manager/server, calling `manager.Publish()` does not use networking--under the hood it uses the go channels that are part of the pub-sub plumbing. You could also wrap the manager in an http handler closure that calls publish as desired.
See the [Examples](/examples/README.md) on how to use the golang and javascript clients as well as how to wrap the `manager.PublishHandler` or call `manager.Publish()` directly.
## How it Works
You can think of the longpoll manager as a goroutine that uses channels to service pub-sub requests. The manager has a `map[string]eventBuffer` (actually a `map[string]*expiringBuffer`) that holds events per category as well as a data structure (another sort of map) for the subscription request book-keeping. The `PublishHandler` and `SubscribeHandler` interact with the manager goroutine via channels.The events are stored using in-memory buffers that have a configured max number of events per category. Optionally, the events can be automatically removed based on a time-to-live setting. Since this is all in-memory, there is an optional add-on for auto-persisting and repopulating data from disk. This allows events to persist across program restarts (not the default option/behavior!) One can also create their own custom add-on as well. See the `Customizing` section.
One important limitation/design-decision to be aware of: the `SubscriptionHandler` supports subscribing to a *single cateogry*. If you want to subscribe to more than one category, you must make more than one call to the subscription handler--or create multiple clients each with a different category. Note however that clients are free to publish to more than one categor--to any category really, unless the manager's publish handler is not being served or there is wrapping handler logic that forbids this. Whether or not this limitation is a big deal depends on how you are using categories. This decision reduces the internal complexity and is likely not to change any time soon.
## Customizing
See [golongpoll.Options](https://pkg.go.dev/github.com/jcuga/golongpoll#Options) on how to configure the longpoll manager. This includes:
* `MaxEventBufferSize` - for the max number of events per category, after which oldest-first is truncated. Defaults to 250.
* `EventTimeToLiveSeconds` - how long events exist in the buffer, defaults to forever (as long as `MaxEventBufferSize` isn't reached).
* `AddOn` - optional way to provide custom behavior. The only add-on at the moment is [FilePersistorAddOn](/fileaddon.go) (Usage [example](/examples/filepersist/filepersist.go)). See [AddOn interface](/addons.go) for creating your own custom add-on.Remember, you don't have to expose `LongpollManager.SubscriptionHandler` and `PublishHandler` directly (or at all). You can wrap them with your own http handler that adds additional logic or validation before invoking the inner handler. See the [authentication example](/examples/authentication/auth.go) for how to require auth via header data before those handlers get called. For publishing, you can also call `manager.Publish()` directly, or wrap the manager via a closure to create a custom http handler that publishes data.
# long polling and gin
Need to add long polling to a Gin HTTP Framework app? Simply wrap golongpoll's manager pub/sub functions with a `gin.Context` and pass to `router.POST` and `router.GET`:
```go
package mainimport (
"net/http""github.com/gin-gonic/gin"
"github.com/jcuga/golongpoll"
)func main() {
// Create longpoll manger with default opts
manager, err := golongpoll.StartLongpoll(golongpoll.Options{})
if err != nil {
panic(err)
}router := gin.Default()
router.POST("/pub", wrapWithContext(manager.PublishHandler))
router.GET("/sub", wrapWithContext(manager.SubscriptionHandler))
router.Run(":8001")
}func wrapWithContext(lpHandler func(http.ResponseWriter, *http.Request)) func(*gin.Context) {
return func(c *gin.Context) {
lpHandler(c.Writer, c.Request)
}
}
```