2014-07-10 12:19:39 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2014-07-29 06:57:07 +00:00
|
|
|
"fmt"
|
2014-07-10 12:19:39 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"runtime"
|
2014-07-29 06:57:07 +00:00
|
|
|
"strconv"
|
2014-07-10 12:19:39 +00:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2014-07-29 06:56:46 +00:00
|
|
|
func StartServer() {
|
|
|
|
port := fmt.Sprintf(":%d", Config.Port)
|
|
|
|
err := http.ListenAndServe(port, nil)
|
|
|
|
if err != nil {
|
|
|
|
Error(err, "Error starting server on port %d", Config.Port)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-10 12:19:39 +00:00
|
|
|
func StatusHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
info := make(map[string]map[string]uint)
|
|
|
|
|
|
|
|
for _, q := range queues {
|
|
|
|
info[q.Name] = map[string]uint{
|
|
|
|
"messages": q.Counter.Distance(),
|
|
|
|
"subscriptions": 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-16 18:57:54 +00:00
|
|
|
for _, r := range pool.Requests {
|
2014-07-10 12:19:39 +00:00
|
|
|
for _, q := range r.Queues {
|
|
|
|
info[q]["subscriptions"]++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-16 19:18:54 +00:00
|
|
|
jsn, _ := json.Marshal(info)
|
|
|
|
w.Write(jsn)
|
2014-07-10 12:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func DebugHandler(w http.ResponseWriter, r *http.Request) {
|
2014-07-16 19:33:27 +00:00
|
|
|
info := make(map[string]interface{})
|
2014-07-29 06:31:42 +00:00
|
|
|
info["version"] = Version
|
2014-07-10 12:19:39 +00:00
|
|
|
info["goroutines"] = runtime.NumGoroutine()
|
|
|
|
|
2014-07-16 19:33:27 +00:00
|
|
|
s, err := storage.Status()
|
|
|
|
if err != nil {
|
|
|
|
Error(err, "Failed to get Kyoto Cabinet status")
|
|
|
|
}
|
2014-07-29 06:57:07 +00:00
|
|
|
s = s[:len(s)-1] // Removing trailing new line
|
|
|
|
|
|
|
|
ks := make(map[string]interface{})
|
|
|
|
tokens := strings.Split(s, "\n")
|
|
|
|
for _, t := range tokens {
|
|
|
|
tt := strings.Split(t, "\t")
|
2014-07-29 06:59:37 +00:00
|
|
|
num, err := strconv.Atoi(tt[1])
|
|
|
|
if err != nil {
|
2014-07-29 06:57:07 +00:00
|
|
|
ks[tt[0]] = tt[1]
|
|
|
|
} else {
|
|
|
|
ks[tt[0]] = num
|
|
|
|
}
|
|
|
|
}
|
|
|
|
info["kyoto_cabinet"] = ks
|
2014-07-16 19:33:27 +00:00
|
|
|
|
2014-07-16 19:18:54 +00:00
|
|
|
jsn, _ := json.Marshal(info)
|
|
|
|
w.Write(jsn)
|
2014-07-10 12:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func PublishHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
defer r.Body.Close()
|
|
|
|
msg, _ := ioutil.ReadAll(r.Body)
|
|
|
|
if len(msg) == 0 {
|
|
|
|
msg = Message(r.FormValue("msg"))
|
|
|
|
}
|
|
|
|
|
2014-07-17 13:22:37 +00:00
|
|
|
qname := r.FormValue("queue")
|
|
|
|
ok := RegisterPublication(qname, msg)
|
2014-07-16 17:47:08 +00:00
|
|
|
|
|
|
|
if ok {
|
|
|
|
w.Write([]byte("OK"))
|
|
|
|
} else {
|
|
|
|
http.Error(w, "FAIL", 500)
|
|
|
|
}
|
2014-07-10 12:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func SubscriptionHandler(w http.ResponseWriter, r *http.Request) {
|
2014-07-17 13:22:37 +00:00
|
|
|
rch := make(chan Response)
|
2014-07-16 17:50:05 +00:00
|
|
|
abort := make(chan bool, 1)
|
2014-07-10 12:19:39 +00:00
|
|
|
req := &Request{
|
2014-07-17 13:22:37 +00:00
|
|
|
Queues: strings.Split(r.FormValue("queues"), ","),
|
|
|
|
ResponseCh: rch,
|
|
|
|
Abort: abort,
|
2014-07-10 12:19:39 +00:00
|
|
|
}
|
2014-07-16 18:57:54 +00:00
|
|
|
go RegisterSubscription(req)
|
2014-07-10 12:19:39 +00:00
|
|
|
|
|
|
|
disconnected := w.(http.CloseNotifier).CloseNotify()
|
|
|
|
finished := make(chan bool)
|
|
|
|
go func() {
|
|
|
|
select {
|
|
|
|
case <-disconnected:
|
2014-07-17 13:22:37 +00:00
|
|
|
close(rch)
|
2014-07-16 17:50:05 +00:00
|
|
|
abort <- true
|
2014-07-10 12:19:39 +00:00
|
|
|
case <-finished:
|
|
|
|
}
|
2014-07-17 13:22:37 +00:00
|
|
|
req.Purge()
|
2014-07-10 12:19:39 +00:00
|
|
|
}()
|
|
|
|
|
2014-07-17 13:22:37 +00:00
|
|
|
res, ok := <-rch
|
|
|
|
if !ok {
|
2014-07-10 12:19:39 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
w.Header().Set("Queue", res.Queue)
|
|
|
|
w.Write(res.Message)
|
|
|
|
|
|
|
|
finished <- true
|
|
|
|
}
|
|
|
|
|
|
|
|
func SetupServer() {
|
|
|
|
http.HandleFunc("/status", StatusHandler)
|
|
|
|
http.HandleFunc("/debug", DebugHandler)
|
|
|
|
http.HandleFunc("/publish", PublishHandler)
|
|
|
|
http.HandleFunc("/subscribe", SubscriptionHandler)
|
|
|
|
}
|