misc post-refactor fixes, refinements
This commit is contained in:
@@ -64,8 +64,8 @@ type PoolStats struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PeerStats struct {
|
type PeerStats struct {
|
||||||
ID string
|
ID string
|
||||||
Worker WorkerStats
|
Session SessionStats
|
||||||
}
|
}
|
||||||
|
|
||||||
type PoolPlugin struct {
|
type PoolPlugin struct {
|
||||||
@@ -82,20 +82,20 @@ type PoolPlugin struct {
|
|||||||
type PoolConfig struct {
|
type PoolConfig struct {
|
||||||
InboxBufferSize int
|
InboxBufferSize int
|
||||||
EventsBufferSize int
|
EventsBufferSize int
|
||||||
WorkerConfig WorkerConfig
|
SessionConfig SessionConfig
|
||||||
RequestHeader http.Header
|
RequestHeader http.Header
|
||||||
}
|
}
|
||||||
|
|
||||||
type PoolOption func(*PoolConfig)
|
type PoolOption func(*PoolConfig)
|
||||||
|
|
||||||
func NewPoolConfig(opts ...PoolOption) (*PoolConfig, error) {
|
func NewPoolConfig(opts ...PoolOption) (*PoolConfig, error) {
|
||||||
workerCfg, _ := NewWorkerConfig()
|
sessionCfg, _ := NewSessionConfig()
|
||||||
defaultHeader := http.Header{}
|
defaultHeader := http.Header{}
|
||||||
defaultHeader.Set("User-Agent", "honeybee/0.1.0")
|
defaultHeader.Set("User-Agent", "honeybee/0.1.0")
|
||||||
cfg := &PoolConfig{
|
cfg := &PoolConfig{
|
||||||
InboxBufferSize: 256,
|
InboxBufferSize: 256,
|
||||||
EventsBufferSize: 10,
|
EventsBufferSize: 10,
|
||||||
WorkerConfig: *workerCfg,
|
SessionConfig: *sessionCfg,
|
||||||
RequestHeader: defaultHeader,
|
RequestHeader: defaultHeader,
|
||||||
}
|
}
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
@@ -119,9 +119,9 @@ func WithEventsBufferSize(value int) PoolOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithWorkerConfig(wc WorkerConfig) PoolOption {
|
func WithSessionConfig(wc SessionConfig) PoolOption {
|
||||||
return func(c *PoolConfig) {
|
return func(c *PoolConfig) {
|
||||||
c.WorkerConfig = wc
|
c.SessionConfig = wc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ func ValidatePoolConfig(c *PoolConfig) error {
|
|||||||
if c.EventsBufferSize < 1 {
|
if c.EventsBufferSize < 1 {
|
||||||
return fmt.Errorf("invalid events buffer size: %d", c.EventsBufferSize)
|
return fmt.Errorf("invalid events buffer size: %d", c.EventsBufferSize)
|
||||||
}
|
}
|
||||||
if err := ValidateWorkerConfig(&c.WorkerConfig); err != nil {
|
if err := ValidateSessionConfig(&c.SessionConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -153,8 +153,8 @@ func ValidatePoolConfig(c *PoolConfig) error {
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
id string
|
id string
|
||||||
worker Worker
|
session *session
|
||||||
}
|
}
|
||||||
|
|
||||||
type Pool struct {
|
type Pool struct {
|
||||||
@@ -240,8 +240,8 @@ func (p *Pool) Stats() PoolStats {
|
|||||||
peerStats := make([]PeerStats, 0, count)
|
peerStats := make([]PeerStats, 0, count)
|
||||||
for id, peer := range p.peers {
|
for id, peer := range p.peers {
|
||||||
peerStats = append(peerStats, PeerStats{
|
peerStats = append(peerStats, PeerStats{
|
||||||
ID: id,
|
ID: id,
|
||||||
Worker: peer.worker.Stats(),
|
Session: peer.session.Stats(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,8 +267,8 @@ func (p *Pool) PeerStats(id string) (PeerStats, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return PeerStats{
|
return PeerStats{
|
||||||
ID: id,
|
ID: id,
|
||||||
Worker: peer.worker.Stats(),
|
Session: peer.session.Stats(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +284,7 @@ func (p *Pool) Close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.closed = true
|
p.closed = true
|
||||||
p.cancel() // closes all workers
|
p.cancel() // closes all sessions
|
||||||
|
|
||||||
// remove all peers
|
// remove all peers
|
||||||
p.peers = make(map[string]*Peer)
|
p.peers = make(map[string]*Peer)
|
||||||
@@ -356,8 +356,8 @@ func (p *Pool) Connect(id string, opts ...ConnectOption) error {
|
|||||||
dialFn = o.dialFn
|
dialFn = o.dialFn
|
||||||
}
|
}
|
||||||
|
|
||||||
wc := p.config.WorkerConfig
|
wc := p.config.SessionConfig
|
||||||
worker, err := NewWorker(p.ctx, id, dialFn, &wc, p.handler)
|
session, err := newSession(p.ctx, id, dialFn, &wc, p.handler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -369,6 +369,7 @@ func (p *Pool) Connect(id string, opts ...ConnectOption) error {
|
|||||||
Retire: func(err error) {
|
Retire: func(err error) {
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
if p.closed {
|
if p.closed {
|
||||||
|
p.mu.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
delete(p.peers, id)
|
delete(p.peers, id)
|
||||||
@@ -378,10 +379,10 @@ func (p *Pool) Connect(id string, opts ...ConnectOption) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.wg.Go(func() {
|
p.wg.Go(func() {
|
||||||
worker.Start(pool)
|
session.Start(pool)
|
||||||
})
|
})
|
||||||
|
|
||||||
p.peers[id] = &Peer{id: id, worker: worker}
|
p.peers[id] = &Peer{id: id, session: session}
|
||||||
|
|
||||||
if p.logger != nil {
|
if p.logger != nil {
|
||||||
p.logger.Debug("registered peer", "peer", id)
|
p.logger.Debug("registered peer", "peer", id)
|
||||||
@@ -413,7 +414,7 @@ func (p *Pool) Remove(id string) error {
|
|||||||
}
|
}
|
||||||
delete(p.peers, id)
|
delete(p.peers, id)
|
||||||
|
|
||||||
peer.worker.Stop()
|
peer.session.Stop()
|
||||||
|
|
||||||
if p.logger != nil {
|
if p.logger != nil {
|
||||||
p.logger.Debug("disconnected from peer", "peer", id)
|
p.logger.Debug("disconnected from peer", "peer", id)
|
||||||
@@ -440,7 +441,7 @@ func (p *Pool) Send(id string, data []byte) error {
|
|||||||
return ErrPeerNotFound
|
return ErrPeerNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
err = peer.worker.Send(data)
|
err = peer.session.Send(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -185,11 +185,11 @@ func TestPoolRemove(t *testing.T) {
|
|||||||
|
|
||||||
func TestPoolDialFailed(t *testing.T) {
|
func TestPoolDialFailed(t *testing.T) {
|
||||||
t.Run("EventDialFailed received after failed dial", func(t *testing.T) {
|
t.Run("EventDialFailed received after failed dial", func(t *testing.T) {
|
||||||
wc, _ := NewWorkerConfig(WithRetryDisabled())
|
wc, _ := NewSessionConfig(WithRetryDisabled())
|
||||||
poolCfg, _ := NewPoolConfig(
|
poolCfg, _ := NewPoolConfig(
|
||||||
WithInboxBufferSize(256),
|
WithInboxBufferSize(256),
|
||||||
WithEventsBufferSize(10),
|
WithEventsBufferSize(10),
|
||||||
WithWorkerConfig(*wc),
|
WithSessionConfig(*wc),
|
||||||
)
|
)
|
||||||
pool, err := NewPool(context.Background(), poolCfg, nil)
|
pool, err := NewPool(context.Background(), poolCfg, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -242,8 +242,8 @@ func TestPoolDialFailed(t *testing.T) {
|
|||||||
|
|
||||||
func TestPoolRetire(t *testing.T) {
|
func TestPoolRetire(t *testing.T) {
|
||||||
t.Run("peer absent and EventRetired emitted after self-retire", func(t *testing.T) {
|
t.Run("peer absent and EventRetired emitted after self-retire", func(t *testing.T) {
|
||||||
wc, _ := NewWorkerConfig(WithRetryDisabled())
|
wc, _ := NewSessionConfig(WithRetryDisabled())
|
||||||
poolCfg, _ := NewPoolConfig(WithWorkerConfig(*wc))
|
poolCfg, _ := NewPoolConfig(WithSessionConfig(*wc))
|
||||||
pool, _ := NewPool(context.Background(), poolCfg, nil)
|
pool, _ := NewPool(context.Background(), poolCfg, nil)
|
||||||
|
|
||||||
pool.dialer = &honeybeetest.MockDialer{
|
pool.dialer = &honeybeetest.MockDialer{
|
||||||
@@ -274,8 +274,8 @@ func TestPoolRetire(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("concurrent Remove and self-retire is safe", func(t *testing.T) {
|
t.Run("concurrent Remove and self-retire is safe", func(t *testing.T) {
|
||||||
wc, _ := NewWorkerConfig(WithRetryDisabled())
|
wc, _ := NewSessionConfig(WithRetryDisabled())
|
||||||
poolCfg, _ := NewPoolConfig(WithWorkerConfig(*wc))
|
poolCfg, _ := NewPoolConfig(WithSessionConfig(*wc))
|
||||||
pool, _ := NewPool(context.Background(), poolCfg, nil)
|
pool, _ := NewPool(context.Background(), poolCfg, nil)
|
||||||
|
|
||||||
pool.dialer = &honeybeetest.MockDialer{
|
pool.dialer = &honeybeetest.MockDialer{
|
||||||
|
|||||||
+37
-44
@@ -24,7 +24,7 @@ var ErrConnectionUnavailable = errors.New("connection unavailable")
|
|||||||
// Config
|
// Config
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
type WorkerConfig struct {
|
type SessionConfig struct {
|
||||||
ConnectionConfig transport.ConnectionConfig
|
ConnectionConfig transport.ConnectionConfig
|
||||||
RetryConfig transport.RetryConfig
|
RetryConfig transport.RetryConfig
|
||||||
RetryDisabled bool
|
RetryDisabled bool
|
||||||
@@ -32,12 +32,12 @@ type WorkerConfig struct {
|
|||||||
ReconnectDelay time.Duration
|
ReconnectDelay time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type WorkerOption func(*WorkerConfig)
|
type SessionOption func(*SessionConfig)
|
||||||
|
|
||||||
func NewWorkerConfig(opts ...WorkerOption) (*WorkerConfig, error) {
|
func NewSessionConfig(opts ...SessionOption) (*SessionConfig, error) {
|
||||||
connCfg, _ := transport.NewConnectionConfig()
|
connCfg, _ := transport.NewConnectionConfig()
|
||||||
retryCfg, _ := transport.NewRetryConfig()
|
retryCfg, _ := transport.NewRetryConfig()
|
||||||
cfg := &WorkerConfig{
|
cfg := &SessionConfig{
|
||||||
ConnectionConfig: *connCfg,
|
ConnectionConfig: *connCfg,
|
||||||
RetryConfig: retryCfg,
|
RetryConfig: retryCfg,
|
||||||
KeepaliveTimeout: 60 * time.Second,
|
KeepaliveTimeout: 60 * time.Second,
|
||||||
@@ -46,44 +46,44 @@ func NewWorkerConfig(opts ...WorkerOption) (*WorkerConfig, error) {
|
|||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(cfg)
|
o(cfg)
|
||||||
}
|
}
|
||||||
if err := ValidateWorkerConfig(cfg); err != nil {
|
if err := ValidateSessionConfig(cfg); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithConnectionConfig(value transport.ConnectionConfig) WorkerOption {
|
func WithConnectionConfig(value transport.ConnectionConfig) SessionOption {
|
||||||
return func(c *WorkerConfig) {
|
return func(c *SessionConfig) {
|
||||||
c.ConnectionConfig = value
|
c.ConnectionConfig = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithRetryConfig(value transport.RetryConfig) WorkerOption {
|
func WithRetryConfig(value transport.RetryConfig) SessionOption {
|
||||||
return func(c *WorkerConfig) {
|
return func(c *SessionConfig) {
|
||||||
c.RetryConfig = value
|
c.RetryConfig = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithRetryDisabled() WorkerOption {
|
func WithRetryDisabled() SessionOption {
|
||||||
return func(c *WorkerConfig) {
|
return func(c *SessionConfig) {
|
||||||
c.RetryDisabled = true
|
c.RetryDisabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When KeepaliveTimeout is set to zero, keepalive functionality is disabled.
|
// When KeepaliveTimeout is set to zero, keepalive functionality is disabled.
|
||||||
func WithKeepaliveTimeout(value time.Duration) WorkerOption {
|
func WithKeepaliveTimeout(value time.Duration) SessionOption {
|
||||||
return func(c *WorkerConfig) {
|
return func(c *SessionConfig) {
|
||||||
c.KeepaliveTimeout = value
|
c.KeepaliveTimeout = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithReconnectDelay(value time.Duration) WorkerOption {
|
func WithReconnectDelay(value time.Duration) SessionOption {
|
||||||
return func(c *WorkerConfig) {
|
return func(c *SessionConfig) {
|
||||||
c.ReconnectDelay = value
|
c.ReconnectDelay = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateWorkerConfig(c *WorkerConfig) error {
|
func ValidateSessionConfig(c *SessionConfig) error {
|
||||||
if !c.RetryDisabled {
|
if !c.RetryDisabled {
|
||||||
if err := transport.ValidateRetryConfig(c.RetryConfig); err != nil {
|
if err := transport.ValidateRetryConfig(c.RetryConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -99,17 +99,10 @@ func ValidateWorkerConfig(c *WorkerConfig) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Worker
|
// Session
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
type Worker interface {
|
type SessionStats struct {
|
||||||
Start(pool PoolPlugin)
|
|
||||||
Stop()
|
|
||||||
Send(data []byte) error
|
|
||||||
Stats() WorkerStats
|
|
||||||
}
|
|
||||||
|
|
||||||
type WorkerStats struct {
|
|
||||||
ConnectionAvailable bool
|
ConnectionAvailable bool
|
||||||
Connection transport.ConnectionStats
|
Connection transport.ConnectionStats
|
||||||
ChanIncoming int
|
ChanIncoming int
|
||||||
@@ -119,7 +112,7 @@ type WorkerStats struct {
|
|||||||
TotalRestarts uint64
|
TotalRestarts uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultWorker struct {
|
type session struct {
|
||||||
url string
|
url string
|
||||||
dialFn func(context.Context) (types.Socket, error)
|
dialFn func(context.Context) (types.Socket, error)
|
||||||
conn atomic.Pointer[transport.Connection]
|
conn atomic.Pointer[transport.Connection]
|
||||||
@@ -128,7 +121,7 @@ type DefaultWorker struct {
|
|||||||
|
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
config WorkerConfig
|
config SessionConfig
|
||||||
handler slog.Handler
|
handler slog.Handler
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
|
|
||||||
@@ -137,28 +130,28 @@ type DefaultWorker struct {
|
|||||||
restartCount *atomic.Uint64
|
restartCount *atomic.Uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWorker(
|
func newSession(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
url string,
|
url string,
|
||||||
dialFn func(context.Context) (types.Socket, error),
|
dialFn func(context.Context) (types.Socket, error),
|
||||||
config *WorkerConfig,
|
config *SessionConfig,
|
||||||
handler slog.Handler,
|
handler slog.Handler,
|
||||||
) (*DefaultWorker, error) {
|
) (*session, error) {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
config, _ = NewWorkerConfig()
|
config, _ = NewSessionConfig()
|
||||||
}
|
}
|
||||||
if err := ValidateWorkerConfig(config); err != nil {
|
if err := ValidateSessionConfig(config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if component.FromContext(ctx) == nil {
|
if component.FromContext(ctx) == nil {
|
||||||
ctx = component.MustNew(ctx, "honeybee", "worker")
|
ctx = component.MustNew(ctx, "honeybee", "session")
|
||||||
} else {
|
} else {
|
||||||
ctx = component.MustExtend(ctx, "worker")
|
ctx = component.MustExtend(ctx, "session")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
w := &DefaultWorker{
|
w := &session{
|
||||||
url: url,
|
url: url,
|
||||||
dialFn: dialFn,
|
dialFn: dialFn,
|
||||||
|
|
||||||
@@ -182,13 +175,13 @@ func NewWorker(
|
|||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *DefaultWorker) Start(pool PoolPlugin) {
|
func (w *session) Start(pool PoolPlugin) {
|
||||||
if w.logger != nil {
|
if w.logger != nil {
|
||||||
w.logger.Debug("starting")
|
w.logger.Debug("starting")
|
||||||
}
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() { w.runSession(w.ctx, pool) })
|
wg.Go(func() { w.run(w.ctx, pool) })
|
||||||
|
|
||||||
if w.logger != nil {
|
if w.logger != nil {
|
||||||
w.logger.Debug("started")
|
w.logger.Debug("started")
|
||||||
@@ -201,7 +194,7 @@ func (w *DefaultWorker) Start(pool PoolPlugin) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *DefaultWorker) runSession(ctx context.Context, pool PoolPlugin) {
|
func (w *session) run(ctx context.Context, pool PoolPlugin) {
|
||||||
for {
|
for {
|
||||||
var retryMgr *transport.RetryManager
|
var retryMgr *transport.RetryManager
|
||||||
if !w.config.RetryDisabled {
|
if !w.config.RetryDisabled {
|
||||||
@@ -298,7 +291,7 @@ func (w *DefaultWorker) runSession(ctx context.Context, pool PoolPlugin) {
|
|||||||
w.conn.Store(nil)
|
w.conn.Store(nil)
|
||||||
pool.Events <- PoolEvent{ID: w.url, Kind: EventDisconnected, At: time.Now()}
|
pool.Events <- PoolEvent{ID: w.url, Kind: EventDisconnected, At: time.Now()}
|
||||||
|
|
||||||
// exit if worker is shutting down
|
// exit if session is shutting down
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
@@ -311,7 +304,7 @@ func (w *DefaultWorker) runSession(ctx context.Context, pool PoolPlugin) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *DefaultWorker) startKeepalive() (
|
func (w *session) startKeepalive() (
|
||||||
stop func(),
|
stop func(),
|
||||||
inactive func() <-chan time.Time,
|
inactive func() <-chan time.Time,
|
||||||
heartbeat func(),
|
heartbeat func(),
|
||||||
@@ -354,14 +347,14 @@ func (w *DefaultWorker) startKeepalive() (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *DefaultWorker) Stop() {
|
func (w *session) Stop() {
|
||||||
if w.logger != nil {
|
if w.logger != nil {
|
||||||
w.logger.Info("shutting down")
|
w.logger.Info("shutting down")
|
||||||
}
|
}
|
||||||
w.cancel()
|
w.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *DefaultWorker) Send(data []byte) error {
|
func (w *session) Send(data []byte) error {
|
||||||
conn := w.conn.Load()
|
conn := w.conn.Load()
|
||||||
if conn == nil {
|
if conn == nil {
|
||||||
// connection not established by session
|
// connection not established by session
|
||||||
@@ -383,7 +376,7 @@ func (w *DefaultWorker) Send(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *DefaultWorker) Stats() WorkerStats {
|
func (w *session) Stats() SessionStats {
|
||||||
connectionAvailable := false
|
connectionAvailable := false
|
||||||
incomingLen := 0
|
incomingLen := 0
|
||||||
connStats := transport.ConnectionStats{}
|
connStats := transport.ConnectionStats{}
|
||||||
@@ -395,7 +388,7 @@ func (w *DefaultWorker) Stats() WorkerStats {
|
|||||||
connStats = conn.Stats()
|
connStats = conn.Stats()
|
||||||
}
|
}
|
||||||
|
|
||||||
return WorkerStats{
|
return SessionStats{
|
||||||
ConnectionAvailable: connectionAvailable,
|
ConnectionAvailable: connectionAvailable,
|
||||||
Connection: connStats,
|
Connection: connStats,
|
||||||
ChanIncoming: incomingLen,
|
ChanIncoming: incomingLen,
|
||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeWorkerContext(t *testing.T) (
|
func makeSessionContext(t *testing.T) (
|
||||||
inbox chan types.InboxMessage,
|
inbox chan types.InboxMessage,
|
||||||
events chan PoolEvent,
|
events chan PoolEvent,
|
||||||
pool PoolPlugin,
|
pool PoolPlugin,
|
||||||
@@ -31,19 +31,19 @@ func makeWorkerContext(t *testing.T) (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeWorker(
|
func makeSession(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
socket *honeybeetest.MockSocket,
|
socket *honeybeetest.MockSocket,
|
||||||
config *WorkerConfig,
|
config *SessionConfig,
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
cancel context.CancelFunc,
|
cancel context.CancelFunc,
|
||||||
) *DefaultWorker {
|
) *session {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if config == nil {
|
if config == nil {
|
||||||
config, _ = NewWorkerConfig(WithReconnectDelay(0 * time.Second))
|
config, _ = NewSessionConfig(WithReconnectDelay(0 * time.Second))
|
||||||
}
|
}
|
||||||
dialFn := func(_ context.Context) (types.Socket, error) { return socket, nil }
|
dialFn := func(_ context.Context) (types.Socket, error) { return socket, nil }
|
||||||
return &DefaultWorker{
|
return &session{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
url: "wss://test",
|
url: "wss://test",
|
||||||
@@ -56,14 +56,14 @@ func makeWorker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWorkerSession(t *testing.T) {
|
func TestSession(t *testing.T) {
|
||||||
t.Run("EventConnected emitted after dial succeeds", func(t *testing.T) {
|
t.Run("EventConnected emitted after dial succeeds", func(t *testing.T) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
mockSocket := honeybeetest.NewMockSocket()
|
mockSocket := honeybeetest.NewMockSocket()
|
||||||
w := makeWorker(t, mockSocket, nil, ctx, cancel)
|
w := makeSession(t, mockSocket, nil, ctx, cancel)
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() {
|
wg.Go(func() {
|
||||||
@@ -80,16 +80,16 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
}, "expected EventConnected")
|
}, "expected EventConnected")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("dial failure exhausted - worker exits cleanly, no connected/disconnected events", func(t *testing.T) {
|
t.Run("dial failure exhausted - session exits cleanly, no connected/disconnected events", func(t *testing.T) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
config, _ := NewWorkerConfig(WithRetryDisabled())
|
config, _ := NewSessionConfig(WithRetryDisabled())
|
||||||
w := makeWorker(t, nil, config, ctx, cancel)
|
w := makeSession(t, nil, config, ctx, cancel)
|
||||||
w.dialFn = func(_ context.Context) (types.Socket, error) {
|
w.dialFn = func(_ context.Context) (types.Socket, error) {
|
||||||
return nil, fmt.Errorf("connection refused")
|
return nil, fmt.Errorf("connection refused")
|
||||||
}
|
}
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() { w.Start(pool) })
|
wg.Go(func() { w.Start(pool) })
|
||||||
@@ -103,7 +103,7 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}, "expected worker to exit after terminal dial failure")
|
}, "expected session to exit after terminal dial failure")
|
||||||
|
|
||||||
honeybeetest.Never(t, func() bool {
|
honeybeetest.Never(t, func() bool {
|
||||||
select {
|
select {
|
||||||
@@ -119,12 +119,12 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
config, _ := NewWorkerConfig(WithRetryDisabled())
|
config, _ := NewSessionConfig(WithRetryDisabled())
|
||||||
w := makeWorker(t, nil, config, ctx, cancel)
|
w := makeSession(t, nil, config, ctx, cancel)
|
||||||
w.dialFn = func(_ context.Context) (types.Socket, error) {
|
w.dialFn = func(_ context.Context) (types.Socket, error) {
|
||||||
return nil, fmt.Errorf("connection refused")
|
return nil, fmt.Errorf("connection refused")
|
||||||
}
|
}
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
retired := atomic.Bool{}
|
retired := atomic.Bool{}
|
||||||
var retiredErr atomic.Pointer[error]
|
var retiredErr atomic.Pointer[error]
|
||||||
@@ -148,7 +148,7 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}, "expected worker to exit cleanly")
|
}, "expected session to exit cleanly")
|
||||||
|
|
||||||
honeybeetest.Never(t, func() bool {
|
honeybeetest.Never(t, func() bool {
|
||||||
select {
|
select {
|
||||||
@@ -164,12 +164,12 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
w := makeWorker(t, nil, nil, ctx, cancel)
|
w := makeSession(t, nil, nil, ctx, cancel)
|
||||||
w.dialFn = func(dialCtx context.Context) (types.Socket, error) {
|
w.dialFn = func(dialCtx context.Context) (types.Socket, error) {
|
||||||
<-dialCtx.Done()
|
<-dialCtx.Done()
|
||||||
return nil, dialCtx.Err()
|
return nil, dialCtx.Err()
|
||||||
}
|
}
|
||||||
_, _, pool := makeWorkerContext(t)
|
_, _, pool := makeSessionContext(t)
|
||||||
|
|
||||||
retired := atomic.Bool{}
|
retired := atomic.Bool{}
|
||||||
pool.Retire = func(_ error) { retired.Store(true) }
|
pool.Retire = func(_ error) { retired.Store(true) }
|
||||||
@@ -187,7 +187,7 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}, "expected worker to exit after Stop")
|
}, "expected session to exit after Stop")
|
||||||
|
|
||||||
assert.False(t, retired.Load(), "expected Retire not called")
|
assert.False(t, retired.Load(), "expected Retire not called")
|
||||||
})
|
})
|
||||||
@@ -197,8 +197,8 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
mockSocket := honeybeetest.NewMockSocket()
|
mockSocket := honeybeetest.NewMockSocket()
|
||||||
w := makeWorker(t, mockSocket, nil, ctx, cancel)
|
w := makeSession(t, mockSocket, nil, ctx, cancel)
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
retired := atomic.Bool{}
|
retired := atomic.Bool{}
|
||||||
pool.Retire = func(_ error) { retired.Store(true) }
|
pool.Retire = func(_ error) { retired.Store(true) }
|
||||||
@@ -222,12 +222,12 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
w := makeWorker(t, nil, nil, ctx, cancel)
|
w := makeSession(t, nil, nil, ctx, cancel)
|
||||||
w.dialFn = func(dialCtx context.Context) (types.Socket, error) {
|
w.dialFn = func(dialCtx context.Context) (types.Socket, error) {
|
||||||
<-dialCtx.Done()
|
<-dialCtx.Done()
|
||||||
return nil, dialCtx.Err()
|
return nil, dialCtx.Err()
|
||||||
}
|
}
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() { w.Start(pool) })
|
wg.Go(func() { w.Start(pool) })
|
||||||
@@ -253,8 +253,8 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
_, mockSocket, _, outgoingData := setupTestConnection(t)
|
_, mockSocket, _, outgoingData := setupTestConnection(t)
|
||||||
w := makeWorker(t, mockSocket, nil, ctx, cancel)
|
w := makeSession(t, mockSocket, nil, ctx, cancel)
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() {
|
wg.Go(func() {
|
||||||
@@ -302,8 +302,8 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w := makeWorker(t, mockSocket, nil, ctx, cancel)
|
w := makeSession(t, mockSocket, nil, ctx, cancel)
|
||||||
inbox, events, pool := makeWorkerContext(t)
|
inbox, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() {
|
wg.Go(func() {
|
||||||
@@ -343,13 +343,13 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
config, _ := NewWorkerConfig(
|
config, _ := NewSessionConfig(
|
||||||
WithReconnectDelay(0),
|
WithReconnectDelay(0),
|
||||||
WithKeepaliveTimeout(60*time.Millisecond),
|
WithKeepaliveTimeout(60*time.Millisecond),
|
||||||
)
|
)
|
||||||
_, mockSocket, incomingData, _ := setupTestConnection(t)
|
_, mockSocket, incomingData, _ := setupTestConnection(t)
|
||||||
w := makeWorker(t, mockSocket, config, ctx, cancel)
|
w := makeSession(t, mockSocket, config, ctx, cancel)
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() { w.Start(pool) })
|
wg.Go(func() { w.Start(pool) })
|
||||||
@@ -400,12 +400,12 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
mockSocket, incomingData, _ := honeybeetest.SetupTestSocket(t)
|
mockSocket, incomingData, _ := honeybeetest.SetupTestSocket(t)
|
||||||
mockSocket.SetPongHandlerFunc = func(h func(string) error) { pongHandler = h }
|
mockSocket.SetPongHandlerFunc = func(h func(string) error) { pongHandler = h }
|
||||||
|
|
||||||
config, _ := NewWorkerConfig(
|
config, _ := NewSessionConfig(
|
||||||
WithReconnectDelay(0),
|
WithReconnectDelay(0),
|
||||||
WithKeepaliveTimeout(60*time.Millisecond),
|
WithKeepaliveTimeout(60*time.Millisecond),
|
||||||
)
|
)
|
||||||
w := makeWorker(t, mockSocket, config, ctx, cancel)
|
w := makeSession(t, mockSocket, config, ctx, cancel)
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() { w.Start(pool) })
|
wg.Go(func() { w.Start(pool) })
|
||||||
@@ -451,13 +451,13 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
config, _ := NewWorkerConfig(
|
config, _ := NewSessionConfig(
|
||||||
WithReconnectDelay(0),
|
WithReconnectDelay(0),
|
||||||
WithKeepaliveTimeout(30*time.Millisecond),
|
WithKeepaliveTimeout(30*time.Millisecond),
|
||||||
)
|
)
|
||||||
_, mockSocket, _, _ := setupTestConnection(t)
|
_, mockSocket, _, _ := setupTestConnection(t)
|
||||||
w := makeWorker(t, mockSocket, config, ctx, cancel)
|
w := makeSession(t, mockSocket, config, ctx, cancel)
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() { w.Start(pool) })
|
wg.Go(func() { w.Start(pool) })
|
||||||
@@ -496,9 +496,9 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
_, mockSocket, incomingData, _ := setupTestConnection(t)
|
_, mockSocket, incomingData, _ := setupTestConnection(t)
|
||||||
w := makeWorker(t, mockSocket, nil, ctx, cancel)
|
w := makeSession(t, mockSocket, nil, ctx, cancel)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() {
|
wg.Go(func() {
|
||||||
@@ -539,9 +539,9 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
mockSocket := honeybeetest.NewMockSocket()
|
mockSocket := honeybeetest.NewMockSocket()
|
||||||
w := makeWorker(t, mockSocket, nil, ctx, cancel)
|
w := makeSession(t, mockSocket, nil, ctx, cancel)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() {
|
wg.Go(func() {
|
||||||
@@ -582,11 +582,11 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("parent context cancel exits cleanly and wg drains", func(t *testing.T) {
|
t.Run("parent context cancel exits cleanly and wg drains", func(t *testing.T) {
|
||||||
parentCtx, parentCancel := context.WithCancel(context.Background())
|
parentCtx, parentCancel := context.WithCancel(context.Background())
|
||||||
workerCtx, workerCancel := context.WithCancel(parentCtx)
|
sessionCtx, sessionCancel := context.WithCancel(parentCtx)
|
||||||
|
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
mockSocket := honeybeetest.NewMockSocket()
|
mockSocket := honeybeetest.NewMockSocket()
|
||||||
w := makeWorker(t, mockSocket, nil, workerCtx, workerCancel)
|
w := makeSession(t, mockSocket, nil, sessionCtx, sessionCancel)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Go(func() {
|
wg.Go(func() {
|
||||||
@@ -603,7 +603,7 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
}, "expected EventConnected")
|
}, "expected EventConnected")
|
||||||
|
|
||||||
// drain events after parent cancel — we don't assert what they are,
|
// drain events after parent cancel — we don't assert what they are,
|
||||||
// only that the worker exits
|
// only that the session exits
|
||||||
parentCancel()
|
parentCancel()
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@@ -622,8 +622,8 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
w := makeWorker(t, nil, nil, ctx, cancel)
|
w := makeSession(t, nil, nil, ctx, cancel)
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
dialErr := errors.New("connection refused")
|
dialErr := errors.New("connection refused")
|
||||||
w.dialFn = func(_ context.Context) (types.Socket, error) {
|
w.dialFn = func(_ context.Context) (types.Socket, error) {
|
||||||
@@ -646,12 +646,12 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
}, "expected EventDialFailed")
|
}, "expected EventDialFailed")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("no EventDialFailed when worker is stopped mid-dial", func(t *testing.T) {
|
t.Run("no EventDialFailed when session is stopped mid-dial", func(t *testing.T) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
w := makeWorker(t, nil, nil, ctx, cancel)
|
w := makeSession(t, nil, nil, ctx, cancel)
|
||||||
_, events, pool := makeWorkerContext(t)
|
_, events, pool := makeSessionContext(t)
|
||||||
|
|
||||||
w.dialFn = func(dialCtx context.Context) (types.Socket, error) {
|
w.dialFn = func(dialCtx context.Context) (types.Socket, error) {
|
||||||
<-dialCtx.Done()
|
<-dialCtx.Done()
|
||||||
@@ -672,7 +672,7 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}, "expected worker to exit after Stop")
|
}, "expected session to exit after Stop")
|
||||||
|
|
||||||
honeybeetest.Never(t, func() bool {
|
honeybeetest.Never(t, func() bool {
|
||||||
select {
|
select {
|
||||||
@@ -685,7 +685,7 @@ func TestWorkerSession(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWorkerSend(t *testing.T) {
|
func TestSession_Send(t *testing.T) {
|
||||||
t.Run("data sent to mock socket", func(t *testing.T) {
|
t.Run("data sent to mock socket", func(t *testing.T) {
|
||||||
conn, _, _, outgoingData := setupTestConnection(t)
|
conn, _, _, outgoingData := setupTestConnection(t)
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
@@ -695,7 +695,7 @@ func TestWorkerSend(t *testing.T) {
|
|||||||
heartbeat := make(chan struct{})
|
heartbeat := make(chan struct{})
|
||||||
heartbeatCount := atomic.Int32{}
|
heartbeatCount := atomic.Int32{}
|
||||||
|
|
||||||
w := &DefaultWorker{
|
w := &session{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
url: "wss://test",
|
url: "wss://test",
|
||||||
@@ -740,7 +740,7 @@ func TestWorkerSend(t *testing.T) {
|
|||||||
heartbeat := make(chan struct{})
|
heartbeat := make(chan struct{})
|
||||||
heartbeatCount := atomic.Int32{}
|
heartbeatCount := atomic.Int32{}
|
||||||
|
|
||||||
w := &DefaultWorker{
|
w := &session{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
url: "wss://test",
|
url: "wss://test",
|
||||||
@@ -768,13 +768,13 @@ func TestWorkerSend(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("returns error if connection is unavailable", func(t *testing.T) {
|
t.Run("returns error if connection is unavailable", func(t *testing.T) {
|
||||||
// no connection available to worker
|
// no connection available to session
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
heartbeat := make(chan struct{})
|
heartbeat := make(chan struct{})
|
||||||
|
|
||||||
w := &DefaultWorker{
|
w := &session{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
url: "wss://test",
|
url: "wss://test",
|
||||||
@@ -23,7 +23,6 @@ var (
|
|||||||
ErrConnectionClosed = errors.New("connection closed")
|
ErrConnectionClosed = errors.New("connection closed")
|
||||||
ErrWriteFailed = errors.New("write failed")
|
ErrWriteFailed = errors.New("write failed")
|
||||||
ErrNilSocket = errors.New("socket cannot be nil")
|
ErrNilSocket = errors.New("socket cannot be nil")
|
||||||
ErrSocketExists = errors.New("socket already exists")
|
|
||||||
ErrFailedWriteDeadline = errors.New("failed to set write deadline")
|
ErrFailedWriteDeadline = errors.New("failed to set write deadline")
|
||||||
ErrPeerClosedClean = errors.New("peer closed connection cleanly")
|
ErrPeerClosedClean = errors.New("peer closed connection cleanly")
|
||||||
ErrPeerClosedUnexpected = errors.New("peer closed connection unexpectedly")
|
ErrPeerClosedUnexpected = errors.New("peer closed connection unexpectedly")
|
||||||
@@ -367,7 +366,12 @@ func (c *Connection) startPinger() {
|
|||||||
timer.Stop()
|
timer.Stop()
|
||||||
return
|
return
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
deadline := time.Now().Add(c.config.WriteTimeout)
|
var deadline time.Time
|
||||||
|
if c.config.WriteTimeout > 0 {
|
||||||
|
deadline = time.Now().Add(c.config.WriteTimeout)
|
||||||
|
} else {
|
||||||
|
deadline = time.Now().Add(15 * time.Second)
|
||||||
|
}
|
||||||
err := c.socket.WriteControl(websocket.PingMessage, nil, deadline)
|
err := c.socket.WriteControl(websocket.PingMessage, nil, deadline)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user