Как следует использовать макрос carine wcar?

Я смущен тем, как следует делать звонки с кармином. Я нашел wcar макрос описан в документах Кармина:

(defmacro wcar [& body] `(car/with-conn pool spec-server1 ~@body))

Мне действительно нужно позвонить wcar каждый раз, когда я хочу поговорить с Redis в дополнение к команде Redis? Или я могу просто назвать это один раз в начале? Если так, как?

Вот как выглядел какой-то код с библиотекой redis Тависрудда (из тестового пакета проекта по сокращению URL моей игрушки):

(deftest test_shorten_doesnt_exist_create_new_next 
  (redis/with-server test-server
    (redis/set "url_counter" 51)
    (shorten test-url)
    (is (= "1g" (redis/get (str "urls|" test-url))))
    (is (= test-url (redis/get "shorts|1g")))))

И теперь я могу заставить его работать только с кармином, написав это так:

(deftest test_shorten_doesnt_exist_create_new_next
  (wcar (car/set "url_counter" 51))
    (shorten test-url)
    (is (= "1g" (wcar (car/get (str "urls|" test-url)))))
    (is (= test-url (wcar (car/get "shorts|1g")))))

Так как правильно его использовать и какую основную концепцию я не понимаю?

2 ответа

Решение

Объяснение Дэна верно.

Carmine по умолчанию использует конвейеризацию ответов, тогда как redis-clojure требует от вас запрашивать конвейеризацию, когда вы этого хотите (используя pipeline макро).

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

Деструктуризация Clojure предоставляет удобный способ работы с конвейерным ответом, но требует написания кода иначе redis-clojure, То, как я написал бы ваш пример, выглядит примерно так (я полагаю, ваш shorten FN имеет побочные эффекты и должен быть вызван до GETs):

(deftest test_shorten_doesnt_exist_create_new_next
  (wcar (car/set "url_counter" 51))
  (shorten test-url)
  (let [[response1 response2] (wcar (car/get (str "urls|" test-url))
                                    (car/get "shorts|1g"))]
    (is (= "1g" response1))
    (is (= test-url response2))))

Итак, мы отправляем первое (SET) запрос к Redis и ожидание ответа (я не уверен, действительно ли это необходимо здесь). Затем мы отправим следующие два (GET) запросы, позволяют Redis поставить в очередь ответы, а затем сразу получить их обратно в виде вектора, который мы деструктурируем.

Поначалу это может показаться ненужным дополнительным усилием, поскольку требует, чтобы вы четко указывали, когда следует получать ответы в очереди, но приносит много преимуществ, включая производительность, четкость и возможность составления команд.

Я бы проверил Touchstone на GitHub, если вы ищете пример того, что я считаю идиоматическим Carmine использовать (просто найдите wcar звонки). (Извините, ТАК мешает мне включить другую ссылку).

В противном случае просто напишите мне по электронной почте (или подайте заявку на GitHub), если у вас есть другие вопросы.

Не волнуйтесь, вы уже используете это правильно.

Функции запроса Redis (такие как get и set, которые вы используете выше) все направляются через другую функцию send-request! который опирается на динамически связанный *context* обеспечить связь. Попытка вызвать любую из этих команд Redis без этого контекста потерпит неудачу с ошибкой "без контекста". with-conn макрос (используется в wcar) устанавливает этот контекст и обеспечивает связь.

wcar макрос тогда просто тонкая обёртка with-conn сделав предположение, что вы будете использовать одни и те же данные соединения для всех запросов Redis.

Пока что все это очень похоже на то, как работает redis-clojure Тависа Радда.

Итак, теперь вопрос в том, зачем Кармине wcar когда Redis-Clojure требуется только один with-server?

И ответ - нет. Помимо иногда, когда это происходит. Кармина with-conn использует Redis "Pipelining" для отправки нескольких запросов с одним и тем же соединением, а затем упаковывает ответы вместе в вектор. Пример из README показывает это в действии.

(wcar (car/ping)
      (car/set "foo" "bar")
      (car/get "foo"))
=> ["PONG" "OK" "bar"]

Здесь вы увидите, что ping, set а также get касается только отправки запроса, оставляя получение ответа до wcar, Это исключает утверждения (или любой доступ к результатам) изнутри wcar и приводит к разделению запросов и множественных wcar звонки, которые у вас есть.

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