|
@@ -13,13 +13,14 @@ import (
|
|
)
|
|
)
|
|
|
|
|
|
type Pool struct {
|
|
type Pool struct {
|
|
- addr string
|
|
|
|
- auth smtp.Auth
|
|
|
|
- max int
|
|
|
|
- created int
|
|
|
|
- clients chan *client
|
|
|
|
- rebuild chan struct{}
|
|
|
|
- mut *sync.Mutex
|
|
|
|
|
|
+ addr string
|
|
|
|
+ auth smtp.Auth
|
|
|
|
+ max int
|
|
|
|
+ created int
|
|
|
|
+ clients chan *client
|
|
|
|
+ rebuild chan struct{}
|
|
|
|
+ mut *sync.Mutex
|
|
|
|
+ lastBuildErr *timestampedErr
|
|
}
|
|
}
|
|
|
|
|
|
type client struct {
|
|
type client struct {
|
|
@@ -27,6 +28,11 @@ type client struct {
|
|
failCount int
|
|
failCount int
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+type timestampedErr struct {
|
|
|
|
+ err error
|
|
|
|
+ ts time.Time
|
|
|
|
+}
|
|
|
|
+
|
|
const maxFails = 4
|
|
const maxFails = 4
|
|
|
|
|
|
var ErrTimeout = errors.New("timed out")
|
|
var ErrTimeout = errors.New("timed out")
|
|
@@ -134,6 +140,7 @@ func (p *Pool) makeOne() {
|
|
if c, err := p.build(); err == nil {
|
|
if c, err := p.build(); err == nil {
|
|
p.clients <- c
|
|
p.clients <- c
|
|
} else {
|
|
} else {
|
|
|
|
+ p.lastBuildErr = ×tampedErr{err, time.Now()}
|
|
p.dec()
|
|
p.dec()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -215,7 +222,7 @@ func (p *Pool) maybeReplace(err error, c *client) {
|
|
p.replace(c)
|
|
p.replace(c)
|
|
return
|
|
return
|
|
|
|
|
|
- shutdown:
|
|
|
|
|
|
+shutdown:
|
|
p.dec()
|
|
p.dec()
|
|
c.Quit()
|
|
c.Quit()
|
|
c.Close()
|
|
c.Close()
|
|
@@ -223,10 +230,15 @@ func (p *Pool) maybeReplace(err error, c *client) {
|
|
|
|
|
|
// Send sends an email via a connection pulled from the Pool. The timeout may
|
|
// Send sends an email via a connection pulled from the Pool. The timeout may
|
|
// be <0 to indicate no timeout. Otherwise reaching the timeout will produce
|
|
// be <0 to indicate no timeout. Otherwise reaching the timeout will produce
|
|
-// ErrTimeout.
|
|
|
|
|
|
+// and error building a connection that occurred while we were waiting, or
|
|
|
|
+// otherwise ErrTimeout.
|
|
func (p *Pool) Send(e *Email, timeout time.Duration) (err error) {
|
|
func (p *Pool) Send(e *Email, timeout time.Duration) (err error) {
|
|
|
|
+ start := time.Now()
|
|
c := p.get(timeout)
|
|
c := p.get(timeout)
|
|
if c == nil {
|
|
if c == nil {
|
|
|
|
+ if p.lastBuildErr != nil && start.Before(p.lastBuildErr.ts) {
|
|
|
|
+ return p.lastBuildErr.err
|
|
|
|
+ }
|
|
return ErrTimeout
|
|
return ErrTimeout
|
|
}
|
|
}
|
|
|
|
|