Example #1
1
File: server.go Project: mc0/okq
func serveClient(client *clients.Client) {
	conn := client.Conn
	rr := redis.NewRespReader(conn)

outer:
	for {
		var command string
		var args []string

		m := rr.Read()
		if m.IsType(redis.IOErr) {
			log.L.Debug(client.Sprintf("client connection error %q", m.Err))
			if len(client.Queues) > 0 {
				consumers.UpdateQueues(client, []string{})
			}
			client.Close()
			return
		}

		parts, err := m.Array()
		if err != nil {
			log.L.Debug(client.Sprintf("error parsing to array: %q", err))
			continue outer
		}
		for i := range parts {
			val, err := parts[i].Str()
			if err != nil {
				log.L.Debug(client.Sprintf("invalid command part %#v: %s", parts[i], err))
				invalidCmdResp.WriteTo(conn)
				continue outer
			}
			if i == 0 {
				command = val
			} else {
				args = append(args, val)
			}
		}

		log.L.Debug(client.Sprintf("%s %#v", command, args))
		commands.Dispatch(client, command, args)
	}
}
Example #2
1
File: commands.go Project: mc0/okq
// Dispatch takes in a client whose command has already been read off the
// socket, a list of arguments from that command (not including the command name
// itself), and handles that command
func Dispatch(client *clients.Client, cmd string, args []string) {
	cmdInfo, ok := commandMap[strings.ToUpper(cmd)]
	if !ok {
		writeErrf(client.Conn, "ERR unknown command %q", cmd)
		return
	}

	if len(args) < cmdInfo.minArgs {
		writeErrf(client.Conn, "ERR missing args")
		return
	}

	ret, err := cmdInfo.f(client, args)
	if err != nil {
		writeErrf(client.Conn, "ERR unexpected server-side error")
		log.L.Print(client.Sprintf("command %s %#v err: %s", cmd, args, err))
		return
	}

	redis.NewResp(ret).WriteTo(client.Conn)
}
Example #3
0
File: commands.go Project: mc0/okq
func qregister(client *clients.Client, args []string) (interface{}, error) {
	err := consumers.UpdateQueues(client, args)
	if err != nil {
		return nil, fmt.Errorf("QREGISTER UpdateQueues: %s", err)
	}
	client.Queues = args

	return okSS, nil
}
Example #4
0
File: commands.go Project: mc0/okq
func qnotify(client *clients.Client, args []string) (interface{}, error) {
	timeout, err := parseInt(args[0], "timeout")
	if err != nil {
		return err, nil
	}

	// ensure the NotifyCh is empty before waiting
	queueName := ""
	client.DrainNotifyCh()

	// check to see if we have any events in the registered queues. We check the
	// list in a randomized order since very active queues in the list may not
	// ever let us check after them in the list, abandoning the rest of the list
	queueNames := client.Queues
	for _, i := range rand.Perm(len(queueNames)) {
		unclaimedKey := db.UnclaimedKey(queueNames[i])

		var unclaimedCount int
		unclaimedCount, err = db.Inst.Cmd("LLEN", unclaimedKey).Int()
		if err != nil {
			return nil, fmt.Errorf("QNOTIFY LLEN unclaimed): %s", err)
		}

		if unclaimedCount > 0 {
			queueName = queueNames[i]
			break
		}
	}

	if queueName == "" {
		select {
		case <-time.After(time.Duration(timeout) * time.Second):
		case queueName = <-client.NotifyCh:
		}
	}

	if queueName != "" {
		return queueName, nil
	}

	return nil, nil
}