Skip to content

stanlry/gopolling

Repository files navigation

GoPolling

Github Action codecov Go Report Card

Simple tool for handling long polling request on server side.

Install

go get github.com/stanlry/gopolling

Example

package main

import (
    "encoding/json"
    "github.com/stanlry/gopolling"
    "log"
    "net/http"
)

var channel = "test"

var mgr = gopolling.New(gopolling.DefaultOption)

func main() {
    http.HandleFunc("/message", func(w http.ResponseWriter, r *http.Request) {
        resp, _ := mgr.WaitForNotice(r.Context(), channel, nil)
        st, _ := json.Marshal(resp)
        w.Write(st)
    })
    
    http.HandleFunc("/notify", func(w http.ResponseWriter, r *http.Request) {
        data := r.URL.Query().Get("data")
        mgr.Notify(channel, data, nil)
    })
        
    log.Println("start serve on :80")
    log.Fatal(http.ListenAndServe(":80", nil))
}

wait for message

curl -s localhsot/message

notify clients

curl -s localhost/notify?data=[your message here]

Usage

Create Polling Manager

var mgr = gopolling.New(gopolling.Option{ 
    // message retention time, default is 60s
    Retention: 60,

    // set the timeout for each request, default 120s   
    Timeout: 1 * time.Minute,  

    // message bus, default use goroutine
    Bus: adapter.NewRedisAdapter(pool),

    // message buffer, default use memory
    Buffer: adapter.NewRedisAdapter(pool),

    // logger interface, currently support zap and logrus, default will not log any error
    Logger: zap.NewExample().Sugar(), 
})

Wait For Notice

wait for notice from listener or notifier

// this function will block until receive a notice or timeout
resp, err := mgr.WaitForNotice(
    // request context
    r.Context(), 
    // channel
    channel, 
    // send the data to listener, it will be discarded if no listener exist
    "data",
})

only wait for notice with matched selector

resp, err := mgr.WaitForSelectedNotice(
    r.Context(),
    channel,
    "data",
    // specify identity in the channel, this selector is essential a string map
    gopolling.S{
        "id": "xxx",
    }
)

Direct Notify

Notify everyone that have been waiting in the channel

mgr.Notify(
    // channel
    channel,
    // data being sent
    "data",
    // selector that specify the receiving side, if no one match the selector, message will be discarded
    gopolling.S{
        "id": "xxx",
    },
)

Event Listener

Listen to event when request was made and reply immediately. The reply message will only notify the one who make the request

// subscribe listener
mgr.SubscribeListener(channel, func(ev gopolling.Event, cb *gopolling.Callback){
    // event data
    st := ev.Data.(string)

    // reply to immediately, you can skip this part if no reply is needed
    cb.Reply("reply data")
}) 

Adapters

Redis

Redis is supported for both message bus and message buffer

pool := &redis.Pool{
	MaxIdle:     1,
	MaxActive:   100,
	IdleTimeout: 5 * time.Minute,
	Dial: func() (redis.Conn, error) {
		option := redis.DialPassword("password")
		con, err := redis.Dial("tcp", "localhost:6379", option)
		if err != nil {
			return nil, err
		}
		return con, err
	},
}

adapter := adapter.NewRedisAdapter(pool)
mgr := gopolling.New(gopolling.Option{
    bus:    adapter,
    buffer: adapter,
})

GCP Pub/Sub

GCP Pub/Sub is supported for message bus

client := pubsub.NewClient(context.Background(), "project-id")
adapter := adapter.NewGCPPubSubAdapter(client)
mgr := gopolling.New(gopolling.Option{
    bus: adapter,
})

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages