### Tundra Example: S3 Datastore Setup Source: https://github.com/taoensso/carmine/wiki/2-Further-usage Configure Tundra with an S3 datastore for offloading data. This snippet shows how to initialize an `s3-datastore` with bucket and folder details. ```clojure (:require [taoensso.carmine.tundra :as tundra :refer (ensure-ks dirty)] [taoensso.carmine.tundra.s3]) ; Add to ns (def my-tundra-store (tundra/tundra-store ;; A datastore that implements the necessary (easily-extendable) protocol: (taoensso.carmine.tundra.s3/s3-datastore {:access-key "" :secret-key ""} "my-bucket/my-folder"))) ;; Now we have access to the Tundra API: (comment (worker my-tundra-store {} {}) ; Create a replication worker (dirty my-tundra-store "foo:bar1" "foo:bar2" ...) ; Queue for replication (ensure-ks my-tundra-store "foo:bar1" "foo:bar2" ...) ; Fetch from replica when necessary ) ``` -------------------------------- ### Map `set` and `get` Commands Using `mapv` Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Illustrates composing Carmine commands by using `mapv` to apply `car/set` and `car/get` to collections of keys and values. ```clojure (let [first-names ["Salvatore" "Rich"] surnames ["Sanfilippo" "Hickey"]] (wcar* (mapv #(car/set %1 %2) first-names surnames) (mapv car/get first-names))) => ["OK" "OK" "Sanfilippo" "Hickey"] ``` -------------------------------- ### Execute Redis Command with wcar Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Use the `wcar` function with your configured options to execute Redis commands. This example pings the Redis server. ```clojure (wcar my-wcar-opts (car/ping)) ; => "PONG" ``` -------------------------------- ### Publish a Message to a Channel Source: https://github.com/taoensso/carmine/wiki/2-Further-usage Publishes a message to a specified channel. This example demonstrates how a single publish can trigger multiple handlers due to pattern matching. ```clojure (wcar* (car/publish "channel1" "Hello to channel1!")) ``` -------------------------------- ### Nested `wcar` for Controlled Composition and Pipelining Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Demonstrates how nesting `wcar` calls allows fine-grained control over the interaction between composition and pipelining, as shown in this example using `hmset`, `hkeys`, and `hget`. ```clojure (let [hash-key "awesome-people"] (wcar* (car/hmset hash-key "Rich" "Hickey" "Salvatore" "Sanfilippo") (mapv (partial car/hget hash-key) ;; Execute with own connection & pipeline then return result ;; for composition: (wcar* (car/hkeys hash-key))))) => ["OK" "Sanfilippo" "Hickey"] ``` -------------------------------- ### Get Documentation for a Redis Command Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Access the documentation for any Carmine-generated Redis command function, such as `car/sort`, using `clojure.repl/doc` to see its signature, description, and availability. ```clojure (clojure.repl/doc car/sort) => "SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination] Sort the elements in a list, set or sorted set. Available since: 1.0.0. Time complexity: O(N+M*log(M)) where N is the number of elements in the list or set to sort, and M the number of returned elements. When the elements are not sorted, complexity is currently O(N) as there is a copy step that will be avoided in next releases." ``` -------------------------------- ### Custom Reply Parsing with `parse` Source: https://github.com/taoensso/carmine/wiki/2-Further-usage Use the `parse` function to apply custom transformations to server replies. This example demonstrates converting replies to lowercase. ```clojure (wcar* (car/ping) (car/parse clojure.string/lower-case (car/ping) (car/ping)) (car/ping)) => ["PONG" "pong" "pong" "PONG"] ``` -------------------------------- ### Execute Custom Lua Script with Carmine Source: https://github.com/taoensso/carmine/wiki/2-Further-usage Define and execute a custom Lua script for Redis operations. This example demonstrates a custom 'set' command using named variables for keys and values. ```clojure (defn my-set [key value] (car/lua "return redis.call('set', _:my-key, 'lua '.. _:my-val)" {:my-key key} ; Named key variables and their values {:my-val value} ; Named non-key variables and their values )) (wcar* (my-set "foo" "bar") (car/get "foo")) => ["OK" "lua bar"] ``` -------------------------------- ### Serialize Rich Clojure Data Types to Redis Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Carmine uses Nippy for seamless support of Clojure's rich data types, automatically serializing them into Redis byte strings. This example shows setting and getting a map containing various types. ```clojure (wcar* (car/set "clj-key" {:bigint (bigint 31415926535897932384626433832795) :vec (vec (range 5)) :set #{true false :a :b :c :d} :bytes (byte-array 5) ;; ... }) (car/get "clj-key")) => ["OK" {:bigint 31415926535897932384626433832795N :vec [0 1 2 3 4] :set #{true false :a :c :b :d} :bytes #}] ``` -------------------------------- ### Generate Keys and Retrieve Values Using `mapv` Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Shows dynamic key generation and retrieval using `mapv` with `car/set` and `car/get`, demonstrating function composition within `wcar*`. ```clojure (wcar* (mapv #(car/set (str "key-" %) (rand-int 10)) (range 3)) (mapv #(car/get (str "key-" %)) (range 3))) => ["OK" "OK" "OK" "OK" "0" "6" "6" "2"] ``` -------------------------------- ### Create a Pub/Sub Listener with Multiple Handlers Source: https://github.com/taoensso/carmine/wiki/2-Further-usage Defines a listener with handlers for specific channels and pattern subscriptions. Ensure the server connection is correctly configured. ```clojure (def my-listener (car/with-new-pubsub-listener (:spec server1-conn) {"channel1" (fn f1 [msg] (println "f1:" msg)) "channel*" (fn f2 [msg] (println "f2:" msg)) "ch*" (fn f3 [msg] (println "f3:" msg))} (car/subscribe "channel1") (car/psubscribe "channel*" "ch*"))) ``` -------------------------------- ### Create a Partial wcar Macro Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Define a convenience macro `wcar*` that pre-configures `wcar` with your connection options. ```clojure (defmacro wcar* [& body] `(car/wcar my-wcar-opts ~@body)) ``` -------------------------------- ### Execute Multiple Pings Using `doall` and `repeatedly` Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Demonstrates using Carmine's command functions like regular Clojure functions by executing multiple `car/ping` commands using `doall` and `repeatedly`. ```clojure (wcar* (doall (repeatedly 5 car/ping))) => ["PONG" "PONG" "PONG" "PONG" "PONG"] ``` -------------------------------- ### Execute Lua Script with Carmine (Direct API) Source: https://github.com/taoensso/carmine/blob/master/wiki/2-Further-usage.md Utilize Carmine's direct API functions like `eval`, `eval-sha`, `eval*`, and `eval-sha*` for executing Lua scripts. These functions offer lower-level control over script execution. ```clojure (car/eval "return redis.call('set', KEYS[1], ARGV[1])" 1 "mykey" "myval") ``` ```clojure (car/eval-sha "" 1 "mykey" "myval") ``` ```clojure (car/eval* "return redis.call('set', KEYS[1], ARGV[1])" 1 "mykey" "myval") ``` ```clojure (car/eval-sha* "" 1 "mykey" "myval") ``` -------------------------------- ### Carmine Helper for ZUNIONSTORE Source: https://github.com/taoensso/carmine/wiki/2-Further-usage Compares the standard 'zunionstore' command with a Carmine helper version 'zunionstore*'. The helper automatically counts the number of keys provided. ```clojure (wcar* (car/zunionstore "dest-key" 3 "zset1" "zset2" "zset3" "WEIGHTS" 2 3 5)) ``` ```clojure (wcar* (car/zunionstore* "dest-key" ["zset1" "zset2" "zset3"] "WEIGHTS" 2 3 5)) ``` -------------------------------- ### Namespace Imports Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Import the necessary Carmine namespace into your Clojure application. ```clojure (ns my-app (:require [taoensso.carmine :as car :refer [wcar]])) ``` -------------------------------- ### Always Return Pipeline-Style Reply Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Request that Carmine always returns a destructurable pipeline-style reply, even for a single command, by using the `:as-pipeline` option. ```clojure (wcar* :as-pipeline (car/ping)) ; => ["PONG"] ; Note the pipeline-style reply ``` -------------------------------- ### Adjust Listener Subscriptions and Handlers Source: https://github.com/taoensso/carmine/wiki/2-Further-usage Dynamically modifies the subscriptions of an existing listener. Unsubscribe from all channels and then subscribe to a new one, or update handlers using swap! on the listener's state. ```clojure (car/with-open-listener my-listener (car/unsubscribe) ; Unsubscribe from every channel (leaving patterns alone) (car/subscribe "channel3")) ``` ```clojure (swap! (:state my-listener) ; { (fn [msg])} assoc "channel3" (fn [x] (println "do something"))) ``` -------------------------------- ### Execute Multiple Redis Commands with Pipelining Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Use `wcar*` to send multiple Redis commands in a single request, leveraging efficient Redis pipelining. The result is a pipeline reply (vector) for easy destructuring. ```clojure (wcar* (car/ping) (car/set "foo" "bar") (car/get "foo")) ; => ["PONG" "OK" "bar"] (3 commands -> 3 replies) ``` -------------------------------- ### Implementing Distributed Locks Source: https://github.com/taoensso/carmine/wiki/2-Further-usage Utilize `taoensso.carmine.locks/with-lock` for safe, synchronized access to shared resources in a distributed environment. Configure connection details, lock identifier, lock duration, and wait time. ```clojure (:require [taoensso.carmine.locks :as locks]) ; Add to `ns` macro (locks/with-lock {:pool {} :spec {}} ; Connection details "my-lock" ; Lock name/identifier 1000 ; Time to hold lock 500 ; Time to wait (block) for lock acquisition (println "This was printed under lock!")) ``` -------------------------------- ### Add Carmine Dependency Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Include the Carmine dependency in your project's build configuration (Leiningen or deps.edn). Replace 'x-y-z' with the actual version. ```clojure Leiningen: [com.taoensso/carmine "x-y-z"] ; or deps.edn: com.taoensso/carmine {:mvn/version "x-y-z"} ``` -------------------------------- ### Configure Redis Connection Pool and Spec Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Define a connection pool and a connection specification for your Redis server. The `my-wcar-opts` map is used for Carmine's `wcar` API. ```clojure (defonce my-conn-pool (car/connection-pool {})) ; Create a new stateful pool (def my-conn-spec {:uri "redis://redistogo:pass@panga.redistogo.com:9475/"}) (def my-wcar-opts {:pool my-conn-pool, :spec my-conn-spec}) ``` -------------------------------- ### Execute Arbitrary Redis Commands with `redis-call` Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md Use the `redis-call` function to issue arbitrary Redis commands, including those from Redis modules or new commands not yet supported by Carmine's auto-generated functions. ```clojure (car/redis-call :my-custom-command "arg1" "arg2") ``` -------------------------------- ### Define and Use a Carmine Message Queue Worker Source: https://github.com/taoensso/carmine/blob/master/wiki/3-Message-queue.md Defines a connection options map, creates a worker for a named queue with a custom handler, and enqueues a message. Dereferencing the worker provides detailed status information. ```clojure (def my-conn-opts {:pool {} :spec {}}) (def my-worker (car-mq/worker my-conn-opts "my-queue" {:handler (fn [{:keys [message attempt]}] (try (println "Received" message) {:status :success} (catch Throwable _ (println "Handler error!") {:status :retry})))})) (wcar* (car-mq/enqueue "my-queue" "my message!")) ;; Deref your worker to get detailed status info @my-worker => {:qname "my-queue" :opts :conn-opts :running? true :nthreads {:worker 1, :handler 1} :stats {:queue-size {:last 1332, :max 1352, :p90 1323, ...} :queueing-time-ms {:last 203, :max 4774, :p90 300, ...} :handling-time-ms {:last 11, :max 879, :p90 43, ...} :counts {:handler/success 5892 :handler/retry 808 :handler/error 2 :handler/backoff 2034 :sleep/end-of-circle 350}}} ``` -------------------------------- ### Handle Server Errors in Pipelined Commands Source: https://github.com/taoensso/carmine/blob/master/wiki/1-Getting-started.md When pipelining commands, if the server replies with an error for a specific command, an exception is thrown and included in the result vector, allowing other commands to complete. ```clojure (wcar* (car/set "foo" "bar") (car/spop "foo") (car/get "foo")) => ["OK" # "bar"] ``` -------------------------------- ### Adjust Listener Subscriptions Source: https://github.com/taoensso/carmine/blob/master/wiki/2-Further-usage.md Modifies the subscriptions of an existing listener. Use `car/unsubscribe` to remove all channel subscriptions while keeping patterns, and `car/subscribe` to add new ones. ```clojure (car/with-open-listener my-listener (car/unsubscribe) ; Unsubscribe from every channel (leaving patterns alone) (car/subscribe "channel3")) ``` -------------------------------- ### Execute Arbitrary Redis Commands Source: https://github.com/taoensso/carmine/wiki/1-Getting-started Use `car/redis-call` to issue arbitrary Redis commands, including those from Redis modules or new commands not yet in Carmine's spec. ```clojure (car/redis-call :command "MYCUSTOMCOMMAND" :args ["arg1" "arg2"]) ``` -------------------------------- ### Serialize Rich Clojure Data Types to Redis Source: https://github.com/taoensso/carmine/wiki/1-Getting-started Carmine uses Nippy for seamless serialization of Clojure's rich data types (like bigints, vectors, sets, byte arrays) to Redis byte strings. ```clojure (wcar* (car/set "clj-key" {:bigint (bigint 31415926535897932384626433832795) :vec (vec (range 5)) :set #{true false :a :b :c :d} :bytes (byte-array 5) ;; ... }) (car/get "clj-key")) => ["OK" {:bigint 31415926535897932384626433832795N :vec [0 1 2 3 4] :set #{true false :a :c :b :d} :bytes #}] ``` -------------------------------- ### Close a Listener Source: https://github.com/taoensso/carmine/wiki/2-Further-usage Properly closes a listener when it is no longer needed to release resources. This is crucial for managing connections effectively. ```clojure (car/close-listener my-listener) ``` -------------------------------- ### Update Listener Handler Source: https://github.com/taoensso/carmine/blob/master/wiki/2-Further-usage.md Updates the handler function for a specific channel or pattern by directly modifying the listener's state. The state is a map from channel/pattern string to a handler function. ```clojure (swap! (:state my-listener) ; { (fn [msg])} assoc "channel3" (fn [x] (println "do something"))) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.