2014-09-16 11:41:48 +00:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"io/ioutil"
|
2014-09-16 11:58:32 +00:00
|
|
|
"net"
|
2014-09-16 11:41:48 +00:00
|
|
|
"net/http"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
2014-09-16 11:58:27 +00:00
|
|
|
"time"
|
2014-09-16 11:41:48 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
publishEndpoint = "/publish"
|
|
|
|
subscribeEndpoint = "/subscribe"
|
2014-09-24 16:13:29 +00:00
|
|
|
flushEndpoint = "/flush"
|
2014-09-16 11:41:48 +00:00
|
|
|
statusEndpoit = "/status"
|
|
|
|
debugEndpoint = "/debug"
|
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
2014-09-16 11:58:27 +00:00
|
|
|
Config struct {
|
|
|
|
Host string
|
|
|
|
Port int
|
|
|
|
Timeout time.Duration
|
|
|
|
}
|
2014-09-16 11:41:48 +00:00
|
|
|
Client struct {
|
|
|
|
Config *Config
|
|
|
|
httpClient *http.Client
|
|
|
|
}
|
|
|
|
Message struct {
|
|
|
|
Queue string
|
|
|
|
Body []byte
|
|
|
|
}
|
|
|
|
QueueInfo struct {
|
|
|
|
Name string
|
|
|
|
Messages int
|
|
|
|
Subscribers int
|
|
|
|
}
|
|
|
|
DebugInfo struct {
|
|
|
|
Version string `json:"version"`
|
2014-09-24 10:39:12 +00:00
|
|
|
Gomaxprocs int `json:"gomaxprocs"`
|
2014-09-16 11:41:48 +00:00
|
|
|
Goroutines int `json:"goroutines"`
|
|
|
|
KyotoCabinet map[string]interface{} `json:"kyoto_cabinet"`
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2014-09-16 12:06:51 +00:00
|
|
|
func NewConfig() *Config {
|
|
|
|
return &Config{
|
|
|
|
Host: "127.0.0.1",
|
|
|
|
Port: 4401,
|
|
|
|
Timeout: 60 * time.Second,
|
|
|
|
}
|
2014-09-16 11:58:27 +00:00
|
|
|
}
|
|
|
|
|
2014-09-16 11:41:48 +00:00
|
|
|
func NewClient(c *Config) *Client {
|
2014-09-16 12:06:51 +00:00
|
|
|
if c == nil {
|
|
|
|
c = NewConfig()
|
|
|
|
}
|
|
|
|
|
|
|
|
transport := http.Transport{
|
|
|
|
Dial: func(network, addr string) (net.Conn, error) {
|
|
|
|
return net.DialTimeout(network, addr, c.Timeout)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
client := http.Client{
|
|
|
|
Transport: &transport,
|
|
|
|
}
|
|
|
|
|
2014-09-16 11:41:48 +00:00
|
|
|
return &Client{
|
|
|
|
Config: c,
|
2014-09-16 12:06:51 +00:00
|
|
|
httpClient: &client,
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-24 11:39:11 +00:00
|
|
|
func (c *Client) Publish(m *Message) bool {
|
2014-09-16 11:41:48 +00:00
|
|
|
rdr := bytes.NewReader(m.Body)
|
|
|
|
url := c.url(publishEndpoint, "?queue=", m.Queue)
|
|
|
|
|
|
|
|
res, err := http.Post(url, "text/plain", rdr)
|
|
|
|
if err != nil {
|
2014-09-24 11:39:11 +00:00
|
|
|
return false
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
defer res.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(res.Body)
|
|
|
|
if err != nil {
|
2014-09-24 11:39:11 +00:00
|
|
|
return false
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|
|
|
|
|
2014-09-24 11:39:11 +00:00
|
|
|
return (string(body) == "OK")
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|
|
|
|
|
2014-09-24 11:39:11 +00:00
|
|
|
func (c *Client) Subscribe(queues ...string) *Message {
|
2014-09-16 11:41:48 +00:00
|
|
|
url := c.url(subscribeEndpoint, "?queues=", strings.Join(queues, ","))
|
2014-09-24 16:13:29 +00:00
|
|
|
head, body := c.get(url)
|
2014-09-16 11:41:48 +00:00
|
|
|
|
2014-09-24 11:39:11 +00:00
|
|
|
return &Message{
|
2014-09-24 16:13:29 +00:00
|
|
|
Queue: head.Get("Queue"),
|
2014-09-16 11:41:48 +00:00
|
|
|
Body: body,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-28 14:17:02 +00:00
|
|
|
func (c *Client) Flush(queues ...string) []*Message {
|
2014-09-24 16:13:29 +00:00
|
|
|
url := c.url(flushEndpoint, "?queues=", strings.Join(queues, ","))
|
|
|
|
_, body := c.get(url)
|
|
|
|
|
|
|
|
var tmp []map[string]string
|
|
|
|
if err := json.Unmarshal(body, &tmp); err != nil {
|
2014-09-28 14:17:02 +00:00
|
|
|
return nil
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|
|
|
|
|
2014-09-28 14:17:02 +00:00
|
|
|
messages := []*Message{}
|
2014-09-24 16:13:29 +00:00
|
|
|
for _, msg := range tmp {
|
|
|
|
messages = append(messages, &Message{msg["queue"], []byte(msg["message"])})
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|
|
|
|
|
2014-09-28 14:17:02 +00:00
|
|
|
return messages
|
2014-09-24 16:13:29 +00:00
|
|
|
}
|
|
|
|
|
2014-09-28 14:17:02 +00:00
|
|
|
func (c *Client) Status() []*QueueInfo {
|
2014-09-24 16:13:29 +00:00
|
|
|
url := c.url(statusEndpoit)
|
|
|
|
_, body := c.get(url)
|
|
|
|
|
2014-09-16 11:41:48 +00:00
|
|
|
tmp := make(map[string]map[string]int)
|
|
|
|
if err := json.Unmarshal(body, &tmp); err != nil {
|
2014-09-28 14:17:02 +00:00
|
|
|
return nil
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|
|
|
|
|
2014-09-28 14:17:02 +00:00
|
|
|
stat := []*QueueInfo{}
|
2014-09-16 11:41:48 +00:00
|
|
|
for queue, info := range tmp {
|
|
|
|
qi := &QueueInfo{
|
|
|
|
Name: queue,
|
|
|
|
Messages: info["messages"],
|
|
|
|
Subscribers: info["subscribers"],
|
|
|
|
}
|
|
|
|
stat = append(stat, qi)
|
|
|
|
}
|
|
|
|
|
2014-09-28 14:17:02 +00:00
|
|
|
return stat
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) Debug() *DebugInfo {
|
|
|
|
url := c.url(debugEndpoint)
|
2014-09-24 16:13:29 +00:00
|
|
|
_, body := c.get(url)
|
|
|
|
|
|
|
|
var dbg DebugInfo
|
|
|
|
if err := json.Unmarshal(body, &dbg); err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return &dbg
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) get(url string) (http.Header, []byte) {
|
2014-09-16 11:41:48 +00:00
|
|
|
res, err := http.Get(url)
|
|
|
|
if err != nil {
|
2014-09-24 16:13:29 +00:00
|
|
|
return nil, nil
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
body, err := ioutil.ReadAll(res.Body)
|
|
|
|
if err != nil {
|
2014-09-24 16:13:29 +00:00
|
|
|
return nil, nil
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|
2014-09-24 11:39:11 +00:00
|
|
|
res.Body.Close()
|
2014-09-16 11:41:48 +00:00
|
|
|
|
2014-09-24 16:13:29 +00:00
|
|
|
return res.Header, body
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) url(path ...string) string {
|
|
|
|
parts := []string{"http://", c.Config.Host, ":", strconv.Itoa(c.Config.Port)}
|
|
|
|
parts = append(parts, path...)
|
|
|
|
|
2014-09-24 11:39:11 +00:00
|
|
|
return strings.Join(parts, "")
|
2014-09-16 11:41:48 +00:00
|
|
|
}
|