func Connect(target string) (Client, error) { conn, err := net.Dial("tcp", target) if err != nil { return nil, err } // hanshake _, cmd, _, err := network.Receive(conn) if err != nil { return nil, err } ch := make(chan PendingOperation) c := &NetworkClient{connectionId: *cmd.Header.ConnectionID, userId: USER_ID, secret: CLIENT_SECRET, sequence: 1, conn: conn, closed: false, error: nil, notifier: ch} go c.listen(ch) return c, nil }
func (self *NetworkClient) listen(notifications <-chan PendingOperation) { pending := make(map[int64]PendingOperation) // pendings for { _, cmd, value, err := network.Receive(self.conn) if err != nil { if !self.closed { self.error = err // TODO: try closing socket } break } var response error if *cmd.Status.Code != kproto.Command_Status_SUCCESS { response = RemoteError{status: *cmd.Status} } // Notify caller // Seems more complicated than it should, but we are optimizing // for when we receive in order for { op := <-notifications // Chances are, it's in order if op.sequence == *cmd.Header.AckSequence { if *cmd.Status.Code == kproto.Command_Status_SUCCESS { // Status SUCCESS switch *cmd.Header.MessageType { case kproto.Command_GET_RESPONSE: // GET op.value <- value case kproto.Command_GETVERSION_RESPONSE: // Get Version op.value <- cmd.Body.KeyValue.DbVersion case kproto.Command_GETNEXT_RESPONSE: // Get Next op.value <- cmd.Body.KeyValue.Key case kproto.Command_GETPREVIOUS_RESPONSE: // Get Previous op.value <- cmd.Body.KeyValue.Key case kproto.Command_GETKEYRANGE_RESPONSE: // Get Key Range op.array <- cmd.Body.Range.Keys default: // PUT, DELETE op.receiver <- response // TODO: send back the actual response } } else { // Status FAILURE op.receiver <- response // TODO: send back the actual response } break } else { // Either we missed it or it hasnt arrived yet. pending[op.sequence] = op op, ok := pending[*cmd.Header.AckSequence] if ok { // this is the case where we missed it op.receiver <- response delete(pending, op.sequence) break } } } } // Notify all pendings that we are closed for business }