github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/metrics/spool/listener.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package spool 5 6 import ( 7 "net" 8 "time" 9 10 "github.com/juju/errors" 11 "gopkg.in/juju/worker.v1" 12 "gopkg.in/tomb.v2" 13 14 "github.com/juju/juju/juju/sockets" 15 jworker "github.com/juju/juju/worker" 16 ) 17 18 const ( 19 // DefaultTimeout specifies the default socket read and write timeout. 20 DefaultTimeout = 3 * time.Second 21 ) 22 23 // ConnectionHandler defines the method needed to handle socket connections. 24 type ConnectionHandler interface { 25 Handle(net.Conn, <-chan struct{}) error 26 } 27 28 type socketListener struct { 29 listener net.Listener 30 t tomb.Tomb 31 32 handler ConnectionHandler 33 } 34 35 // NewSocketListener returns a new socket listener struct. 36 func NewSocketListener(socketPath string, handler ConnectionHandler) (*socketListener, error) { 37 listener, err := sockets.Listen(socketPath) 38 if err != nil { 39 return nil, errors.Trace(err) 40 } 41 sListener := &socketListener{listener: listener, handler: handler} 42 sListener.t.Go(sListener.loop) 43 return sListener, nil 44 } 45 46 // Stop closes the listener and releases all resources 47 // used by the socketListener. 48 func (l *socketListener) Stop() error { 49 l.t.Kill(nil) 50 err := l.listener.Close() 51 if err != nil { 52 logger.Errorf("failed to close the collect-metrics listener: %v", err) 53 } 54 return l.t.Wait() 55 } 56 57 func (l *socketListener) loop() error { 58 for { 59 conn, err := l.listener.Accept() 60 if err != nil { 61 return errors.Trace(err) 62 } 63 go func() { 64 err := l.handler.Handle(conn, l.t.Dying()) 65 if err != nil { 66 // log the error and continue 67 logger.Errorf("request handling failed: %v", err) 68 } 69 }() 70 } 71 } 72 73 // NewPeriodicWorker returns a periodic worker, that will call a stop function 74 // when it is killed. 75 func NewPeriodicWorker(do jworker.PeriodicWorkerCall, period time.Duration, newTimer func(time.Duration) jworker.PeriodicTimer, stop func()) worker.Worker { 76 return &periodicWorker{ 77 Worker: jworker.NewPeriodicWorker(do, period, newTimer, jworker.Jitter(0.2)), 78 stop: stop, 79 } 80 } 81 82 type periodicWorker struct { 83 worker.Worker 84 stop func() 85 } 86 87 // Kill implements the worker.Worker interface. 88 func (w *periodicWorker) Kill() { 89 w.stop() 90 w.Worker.Kill() 91 }