resend on expired endpoint

This commit is contained in:
Josh Baker 2017-02-10 05:27:02 -07:00
parent 56e0bac24c
commit 22f1b1bd81
5 changed files with 41 additions and 28 deletions

View File

@ -57,7 +57,7 @@ func (conn *DisqueEndpointConn) Send(msg string) error {
conn.mu.Lock() conn.mu.Lock()
defer conn.mu.Unlock() defer conn.mu.Unlock()
if conn.ex { if conn.ex {
return errors.New("expired") return errExpired
} }
conn.t = time.Now() conn.t = time.Now()
if conn.conn == nil { if conn.conn == nil {

View File

@ -9,6 +9,8 @@ import (
"time" "time"
) )
var errExpired = errors.New("expired")
// EndpointProtocol is the type of protocol that the endpoint represents. // EndpointProtocol is the type of protocol that the endpoint represents.
type EndpointProtocol string type EndpointProtocol string
@ -36,9 +38,9 @@ type Endpoint struct {
} }
} }
Redis struct { Redis struct {
Host string Host string
Port int Port int
Channel string Channel string
} }
} }
@ -82,30 +84,42 @@ func (epc *EndpointManager) Validate(url string) error {
} }
func (epc *EndpointManager) Send(endpoint, val string) error { func (epc *EndpointManager) Send(endpoint, val string) error {
epc.mu.Lock() for {
conn, ok := epc.conns[endpoint] epc.mu.Lock()
if !ok || conn.Expired() { conn, ok := epc.conns[endpoint]
ep, err := parseEndpoint(endpoint) if !ok || conn.Expired() {
ep, err := parseEndpoint(endpoint)
if err != nil {
epc.mu.Unlock()
return err
}
switch ep.Protocol {
default:
return errors.New("invalid protocol")
case HTTP:
conn = newHTTPEndpointConn(ep)
case Disque:
conn = newDisqueEndpointConn(ep)
case GRPC:
conn = newGRPCEndpointConn(ep)
case Redis:
conn = newRedisEndpointConn(ep)
}
epc.conns[endpoint] = conn
}
epc.mu.Unlock()
err := conn.Send(val)
if err != nil { if err != nil {
epc.mu.Unlock() if err == errExpired {
// it's possible that the connection has expired in-between
// the last conn.Expired() check and now. If so, we should
// just try the send again.
continue
}
return err return err
} }
switch ep.Protocol { return nil
default:
return errors.New("invalid protocol")
case HTTP:
conn = newHTTPEndpointConn(ep)
case Disque:
conn = newDisqueEndpointConn(ep)
case GRPC:
conn = newGRPCEndpointConn(ep)
case Redis:
conn = newRedisEndpointConn(ep)
}
epc.conns[endpoint] = conn
} }
epc.mu.Unlock()
return conn.Send(val)
} }
func parseEndpoint(s string) (Endpoint, error) { func parseEndpoint(s string) (Endpoint, error) {

View File

@ -57,7 +57,7 @@ func (conn *GRPCEndpointConn) Send(msg string) error {
conn.mu.Lock() conn.mu.Lock()
defer conn.mu.Unlock() defer conn.mu.Unlock()
if conn.ex { if conn.ex {
return errors.New("expired") return errExpired
} }
conn.t = time.Now() conn.t = time.Now()
if conn.conn == nil { if conn.conn == nil {

View File

@ -2,7 +2,6 @@ package endpoint
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -48,7 +47,7 @@ func (conn *HTTPEndpointConn) Send(msg string) error {
conn.mu.Lock() conn.mu.Lock()
defer conn.mu.Unlock() defer conn.mu.Unlock()
if conn.ex { if conn.ex {
return errors.New("expired") return errExpired
} }
conn.t = time.Now() conn.t = time.Now()
if conn.client == nil { if conn.client == nil {

View File

@ -56,7 +56,7 @@ func (conn *RedisEndpointConn) Send(msg string) error {
defer conn.mu.Unlock() defer conn.mu.Unlock()
if conn.ex { if conn.ex {
return errors.New("expired") return errExpired
} }
conn.t = time.Now() conn.t = time.Now()