title: How to handle client concurrency with Go's net.TCPConn
body: <p>I have a legacy server I communicate with over TCP. I wrote the <code>Client</code> to handle communication. It works fine via command line in a single threaded environment, but when handling concurrent calls it obviously fails because of the single, shared TCPConn.</p>
  
  <p>The way a session works on this legacy server, I have to do the following steps:</p>
  
  <ul>
  <li>Open TCPConn</li>
  <li>Login (authenticate with server)</li>
  <li>Call multiple separate commands (ie AddUser, GroupAdd) - There can be many and are slow.</li>
  <li>Logout</li>
  <li>Close TCPConn</li>
  </ul>
  
  <p>Despite having a sessionID, this must all happen via the same TCP connection.</p>
  
  <p>This has worked for years, but now that the API server is getting busier, if clients hit the API at the same time the communication over the TCPConn gets messed up. This is obvious why this is happening. Now I'm looking for an ideal solution to keep it from happening.</p>
  
  <p>My first thought was to transparently have a connection pool like the SQL drivers do. The problem here is that, I believe, that each SQL <code>Query()</code>, <code>QueryRow()</code>, etc can run independently so the driver can get a TCPConn from the connection pool, query, then return the TCPConn to the pool. In my case though, I need to hold that TCPConn for the life of multiple queries. Because of this it can't really be transparent since I need to manually return the TCPConn back to the pool, in each service, since the client cant return it after each query.</p>
  
  <p>The second thought, which seems kinda gross is to put all that logic in <em>each</em> handler (get the conn, instantiate the <code>Client</code> and instantiate one or more <code>Service</code>(s)). This seem redundant and as the handler count keeps growing, its just tons of boilerplate. This would have a released conn from the pool in each handler as well as a <code>Client</code> and <code>Service</code> in each handler, then return the conn to the pool at the end.</p>
  
  <p>Here is the example code below.</p>
  
  <p><code>client.go</code></p>
  
  <pre><code>package whatever
  
  import (
          "fmt"
          "log"
          "net"
          "net/http"
  )
  
  // Response from Client
  type Response []byte
  
  type Client struct {
          conn      *net.TCPConn
          username  string
          password  string
          sessionID string
  }
  
  // Open and Close the TCPConn
  func (c *Client) open() error  { return nil }
  func (c *Client) close() error { return nil }
  
  // Login and Logout will call open and close respectively.  Login calls Run()
  // with user/pass and gets back a sessionID which is set on the struct.
  func (c *Client) Login() error  { return nil }
  func (c *Client) Logout() error { return nil }
  
  // Run sends commands to the server over the Client.conn and returns a Repsonse
  // byte slice.
  func (c *Client) Run(cmd string) (Response, error) { return Response{}, nil }
  </code></pre>
  
  <p><code>service.go</code></p>
  
  <pre><code>// UserService provides services to act on users
  type UserService struct {
          client *Client
  }
  
  // AddUserGroup adds a user and then adds them to GroupA. 
  func (s *UserService) AddUserGroup() error {
          err := s.Client.Login()
          if err != nil {
                  return err
          }
          defer s.Client.Logout()
  
          resp, err := s.Client.Run("CreateUser Bob 46 'Los Angeles'")
          if err != nil {
                  return err
          }
  
          userID := resp[1]
  
          cmd := fmt.Sprintf("GroupAdd %v GroupA", userID)
          resp, _ := s.Client.Run(cmd)
          if err != nil {
                  return err
          }
  
          return nil
  }
  </code></pre>
  
  <p><code>this-works-command-line.go</code></p>
  
  <pre><code>func main() {
          c := Client{username: "user", "password": "pass"}
  
          svc := UserService{client: &amp;c}
          err := svc.AddUserGroup()
          if err != nil {
                  log.Fatal(err)
          }
  }
  </code></pre>
  
  <p><code>this-does-not-work-api.go</code></p>
  
  <pre><code>type Server struct {
          Svc *UserService
  }
  
  func (s *Server) AddUserGroupHandler() http.HandlerFunc {
          return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                  err := s.Svc.AddUserGroup()
                  if err != nil {
                          w.WriteHeader(http.StatusInternalServerError)
                          return
                  }
                  w.WriteHeader(http.StatusCreated)
          })
  }
  
  func main() {
          c := &amp;Client{username: "user", password: "pass"}
          svc := &amp;UserService{client: c}
  
          server := Server{Svc: svc}
          err := svc.AddUserGroup()
          if err != nil {
                  log.Fatal(err)
          }
  
          http.Handle("/foo", server.AddUserGroupHandler())
          log.Fatal(http.ListenAndServe(":8080", nil))
  }
  </code></pre>
  
  <p>Again, if that endpoint gets hit multiple times the same TCPConn will get used and will call <code>Login()</code> or something else while the previous call is being handled.</p>
  
  <p>I can't seem to find a common pattern to handle this. My final thought is to just accept the incoming request and stick it in a DB or redis and have a worker service pick it up later.</p>
  
  <p>Maybe I'm just not using the right terminology to search.</p>
  
  <p>Any help is appreciated.</p>