An opinionated Clojure library wrapping Aerospike Java Client.
4.9.0
1.11.0
CompletableFuture
based API.deref
if you like.deref
(@
) the returned future object.
For a more sophisticated coordination, a variety of control mechanisms can be used by directly using Java's
CompletableFuture
API or the more Clojure friendly promesa (which is also used internally),
or via the library using transcoders or
hooks.user=> (require '[aerospike-clj.client :as aero])
nil
user=> (def c (aero/init-simple-aerospike-client
#_=> ["aerospike-001.com", "aerospik-002.com"] "my-ns" {:enable-logging true}))
It is possible to inject additional asynchronous user-defined behaviour. To do that add an implementation of the
ClientEvents
protocol during client initialization or per operation.
Some useful info is passed in-order to support metering and to read client configuration. op-start-time
is
(System/nanoTime)
.
see more here.
(let [c (aero/init-simple-aerospike-client
["localhost"]
"test"
{:client-events (reify ClientEvents
(on-success [_ op-name op-result index op-start-time]
(println op-name "success!")))
(on-failure [_ op-name op-ex index op-start-time]
(println "oh-no" op-name "failed on index" index)))})]
(get-single c "index" "set-name"))
; for better performance, a `deftype` might be preferred over `reify`, if possible.
For demo purposes we will use a docker based local DB:
$ sudo docker run -d --name aerospike -p 3000:3000 -p 3001:3001 -p 3002:3002 -p 3003:3003 aerospike
And connect to it:
user=> (def c (aero/init-simple-aerospike-client ["localhost"] "test"))
#'user/db
user=> (require '[promesa.core :as p])
nil
user=> (aero/put c "index" "set-name" 42 1000)
#object[java.util.concurrent.CompletableFuture 0x6264b083 "pending"]
user=> (def f (aero/get-single c "index" "set-name"))
#'user/f
user=> (p/chain (aero/get-single c "index" "set-name")
#_=> :ttl
#_=> aero/expiry-unix
#_=> #(java.time.Instant/ofEpochSecond %)
#_=> str
#_=> println)
2020-08-13T09:52:49Z
#object[java.util.concurrent.CompletableFuture 0x654830f5 "pending"]
We actually get back a record with the payload, the DB generation and the TTL (in an Aerospike style EPOCH format).
user=> @(aero/get-single c "index" "set-name")
#aerospike_clj.client.AerospikeRecord{:payload 42, :gen 1, :ttl 285167713}
Aerospike returns a TTL on the queried records that is epoch style, but with a different "beginning of time" which is "2010-01-01T00:00:00Z".
Call expiry-unix
with the returned TTL to get a TTL relative to the UNIX epoch.
Executed via running lein test
.
Testing is performed against a local Aerospike docker container.
For unit tests purposes you can use a mock client that implements the client protocols: MockClient
.
Usage:
(ns com-example.app
(:require [clojure.test :refer [deftest use-fixtures]]
[aerospike-clj.protocols :as pt]
[aerospike-clj.mock-client :as mock])
(:import [aerospike_clj.client SimpleAerospikeClient]))
(def ^:dynamic ^SimpleAerospikeClient client nil)
(defn- bind-client-to-mock [test-fn]
(binding [client (mock/create-instance)]
(test-fn)))
(use-fixtures :each bind-client-to-mock)
(deftest ...) ;; define your application unit tests as usual
The sample code executes on every test run. It initializes the mock with a proper type hint so you can just invoke all client protocol methods on it.
Note: If the production client is initiated using a state management framework, you would also need to stop and restart the state on each test run.
PRs are welcome with these rules:
project.clj
according
to Semantic Versioning.SNAPSHOT
, e.g. 1.0.2-SNAPSHOT
.
Once it will be merged into master
this suffix would be trimmed before release.Distributed under the Apache 2.0 License - found here.
Can you improve this documentation? These fine people already did:
Ido Barkan, asaf.chelouche, idantavor, yaron.elyashiv, Yaron Elyashiv & Sharone ZitzmanEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close