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  }