diff --git a/README.md b/README.md index 79e7f0c..00abfdf 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Flags are supplied to the compiled go program in the form ```-flag=stuff```. | Flag | Description | Default | | ---- | ----------- | ------- | | listen | Port number to listen on | 8080 | +| redis | Host and port of redis | :6379 | ## API @@ -18,7 +19,7 @@ Flags are supplied to the compiled go program in the form ```-flag=stuff```. GET /subscribe/:userid/client/:clientid ``` -Subscribe to a user. Every time a user pings this service, the time will be sent to all subscribed users. +Subscribe to a user. Every time a user pings this service, the time will be sent to all subscribed users. Upon subscription, if it exists, the last cached time of the target user will be pushed immediately to the stream. ```js const es = new EventSource(`${host}/subscribe/${user}/client/${device}`); diff --git a/main.go b/main.go index 3f5e455..0ad68e4 100644 --- a/main.go +++ b/main.go @@ -9,9 +9,11 @@ import ( "time" "github.com/julienschmidt/httprouter" + "github.com/go-redis/redis" ) var listen string +var redisHost string type RawClient struct { UserId string @@ -19,14 +21,23 @@ type RawClient struct { } var connections map[RawClient][]chan []byte +var redisClient *redis.Client func main() { // Parse flags flag.StringVar(&listen, "listen", ":8080", "host and port to listen on") + flag.StringVar(&redisHost, "redis", ":6379", "host and port of redis") flag.Parse() connections = make(map[RawClient][]chan []byte) + // Redis + redisClient = redis.NewClient(&redis.Options{ + Addr: redisHost, + Password: "", + DB: 0, + }) + // Routes router := httprouter.New() router.GET("/subscribe/:userid/client/:clientid", Subscribe) @@ -59,6 +70,13 @@ func Subscribe(w http.ResponseWriter, r *http.Request, p httprouter.Params) { resClosed := w.(http.CloseNotifier).CloseNotify() ticker := time.NewTicker(25 * time.Second) + // Push cached value (if it exists) to the connection + cachedTime, err := redisClient.Get(client.UserId + client.ClientId).Result() + if err == nil { + fmt.Fprintf(w, "data: %s\n\n", cachedTime) + flusher.Flush() + } + for { select { case msg := <- recv: @@ -81,10 +99,12 @@ func PostTime(w http.ResponseWriter, r *http.Request, p httprouter.Params) { ClientId: p.ByName("clientid"), } - time := time.Now().UTC().Unix() + time := []byte(strconv.FormatInt(time.Now().UTC().Unix(), 10)) // UTC Epoch Time in []byte + key := client.UserId + client.ClientId + _ = redisClient.Set(key, time, 0) for _, connection := range connections[client] { - connection <- []byte(strconv.FormatInt(time, 10)) + connection <- time } w.WriteHeader(http.StatusOK)