code: func (nc *Conn) drainConnection() {
  	// Snapshot subs list.
  	nc.mu.Lock()
  	subs := make([]*Subscription, 0, len(nc.subs))
  	for _, s := range nc.subs {
  		subs = append(subs, s)
  	}
  	errCB := nc.Opts.AsyncErrorCB
  	drainWait := nc.Opts.DrainTimeout
  	nc.mu.Unlock()
  
  	// for pushing errors with context.
  	pushErr := func(err error) {
  		nc.mu.Lock()
  		nc.err = err
  		if errCB != nil {
  			nc.ach.push(func() { errCB(nc, nil, err) })
  		}
  		nc.mu.Unlock()
  	}
  
  	// Do subs first
  	for _, s := range subs {
  		if err := s.Drain(); err != nil {
  			// We will notify about these but continue.
  			pushErr(err)
  		}
  	}
  
  	// Wait for the subscriptions to drop to zero.
  	timeout := time.Now().Add(drainWait)
  	for time.Now().Before(timeout) {
  		if nc.NumSubscriptions() == 0 {
  			break
  		}
  		time.Sleep(10 * time.Millisecond)
  	}
  
  	// Check if we timed out.
  	if nc.NumSubscriptions() != 0 {
  		pushErr(ErrDrainTimeout)
  	}
  
  	// Flip State
  	nc.mu.Lock()
  	nc.status = DRAINING_PUBS
  	nc.mu.Unlock()
  
  	// Do publish drain via Flush() call.
  	err := nc.Flush()
  	if err != nil {
  		pushErr(err)
  		nc.Close()
  		return
  	}
  
  	// Move to closed state.
  	nc.Close()
  }
docs: // drainConnection will run in a separate Go routine and will
  // flush all publishes and drain all active subscriptions.