github.com/cmd-stream/base-go@v0.0.0-20230813145615-dd6ac24c16f5/server/server.go (about) 1 package server 2 3 import ( 4 "net" 5 "sync" 6 7 "github.com/cmd-stream/base-go" 8 "github.com/ymz-ncnk/jointwork-go" 9 ) 10 11 // Server is a cmd-stream server. 12 type Server struct { 13 Conf Conf 14 Delegate base.ServerDelegate 15 receiver *ConnReceiver 16 mu sync.Mutex 17 } 18 19 // Serve accepts incoming connections on the listener and processes them using 20 // the configured number of Workers. 21 // 22 // Each Worker can handle one connection at a time using a delegate. 23 // 24 // Always returns a non-nil error. If Conf.WorkersCount == 0, returns 25 // ErrNoWorkers. If Server was shutdown returns ErrShutdown, if was closed - 26 // ErrClosed. 27 func (s *Server) Serve(listener base.Listener) (err error) { 28 if s.Conf.WorkersCount <= 0 { 29 return ErrNoWorkers 30 } 31 conns := make(chan net.Conn, s.Conf.WorkersCount) 32 s.setUpReceiver(listener, conns) 33 var ( 34 tasks = s.makeTasks(conns, s.Delegate) 35 jw = jointwork.New(tasks) 36 ) 37 if err = jw.Run(); err == nil { 38 return ErrShutdown 39 } 40 firstErr := err.(interface{ Get(i int) error }).Get(0) 41 return firstErr.(*jointwork.TaskError).Cause() 42 } 43 44 // Shutdown stops Server from receiving new connections. 45 // 46 // If Server is not serving returns ErrNotServing. 47 func (s *Server) Shutdown() (err error) { 48 if !s.serving() { 49 return ErrNotServing 50 } 51 return s.receiver.Shutdown() 52 } 53 54 // Close closes Server, all existing connections will be closed. 55 // 56 // If Server is not serving returns ErrNotServing. 57 func (s *Server) Close() (err error) { 58 if !s.serving() { 59 return ErrNotServing 60 } 61 return s.receiver.Stop() 62 } 63 64 func (s *Server) setUpReceiver(listener base.Listener, conns chan net.Conn) { 65 s.mu.Lock() 66 s.receiver = NewConnReceiver(s.Conf.ConnReceiverConf, listener, conns) 67 s.mu.Unlock() 68 } 69 70 func (s *Server) makeTasks(conns chan net.Conn, delegate base.ServerDelegate) ( 71 tasks []jointwork.Task) { 72 tasks = make([]jointwork.Task, 1+s.Conf.WorkersCount) 73 tasks[0] = s.receiver 74 for i := 1; i < len(tasks); i++ { 75 tasks[i] = NewWorker(conns, delegate, s.Conf.LostConnCallback) 76 } 77 return 78 } 79 80 func (s *Server) serving() bool { 81 s.mu.Lock() 82 defer s.mu.Unlock() 83 return s.receiver != nil 84 }