Redis не возвращает WRONGTYPE как ошибку в транзакции

Извиняюсь, если это уже спрашивали. Во-первых, позвольте мне показать, как воспроизвести мою проблему:

  1. Запустите Redis в док-контейнере
  2. Подключитесь к Redis и выполните следующую команду:
> SET test 10
  1. В Go запустите этот код:
func main() {
    redisClient := getConnection() // Abstracting get connection for simplicity

    r, err := redisClient.Do("HSET", "test", "f1", "v1", "f2", "v2")
    fmt.Printf("%+v e: %+v\n")
}

Честно говоря, на этом шаге отображается следующая ошибка (это означает err != nil):

WRONGTYPE Operation against a key holding the wrong kind of value e: WRONGTYPE Operation against a key holding the wrong kind of value
  1. Для сравнения выполните следующий код:
func main() {
    redisClient := getConnection()

    redisClient.Send("MULTI")

    redisClient.Send("HSET", "test", "f1", "v1", "f2", "v2")

    r, err := redisClient.Do("EXEC")
    fmt.Printf("%+v e: %+v\n")
}

Печатается строка:

WRONGTYPE Operation against a key holding the wrong kind of value e: <nil>

Мне это кажется непоследовательным, так как я ожидаю, что MULTI также вернет WRONGTYPE в переменной ошибки.

Это преднамеренное поведение или я что-то упустил?

Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
0
0
353
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для каждой команды в транзакции Redis есть два результата. Один результат добавления команды в транзакцию, а другой результат выполнения команды в транзакции.

Метод Do возвращает результат добавления команды в транзакцию.

Команда Redis EXEC возвращает массив, каждый элемент которого является результатом выполнения команды в транзакции. Изучите каждый элемент, чтобы проверить отдельные ошибки команды:

values, err := redis.Values(redisClient.Do("EXEC"))
if err != nil {
    // Handle error
}
if err, ok := values[0].(redis.Error); ok {
    // Handle error for command 0.
    // Adjust the index to match the actual index of 
    // of the HMSET command in the transaction.
}

Может быть полезна вспомогательная функция для проверки ошибок команды транзакции:

func execValues(reply interface{}, err error) ([]interface{}, error) {
    if err != nil {
        return nil, err
    }
    values, ok := reply.([]interface{})
    if !ok {
        return nil, fmt.Errorf("unexpected type for EXEC reply, got type %T", reply)
    }
    for _, v := range values {
        if err, ok := v.(redis.Error); ok {
            return values, err
        }
    }
    return values, nil
}

Используйте это так:

values, err := execValues(redisClient.Do("EXEC"))
if err != nil {
    // Handle error.
}

Спасибо. Я попробую позже сегодня. Однако меня смущает то, что в документации указано, что «если какой-либо из полученных ответов является ошибкой, то Do возвращает ошибку» (pkg.go.dev/github.com/gomodule/redigo/redis#hdr-Pipelining )‌​. Это наводит меня на мысль, что если какая-либо команда завершится ошибкой, я должен получить ошибку при выполнении Do("EXEC").

Rick 10.12.2020 11:21

@Rick Do возвращает ошибку добавления команды в транзакцию. Изучите результат EXEC, чтобы получить ошибку выполнения команды в транзакции.

Cerise Limón 10.12.2020 16:46

Другие вопросы по теме