Liking cljdoc? Tell your friends :D

Aerospike-clj

An opinionated Clojure library wrapping Aerospike Java Client.

Build Status

Docs:

Generated docs

Tutorial:

here.

More advanced docs:

Requirements:

  • Java 8
  • Clojure 1.8

Features:

  • Converts Java client's callback model into a future (manifold/deferred) based API.
  • Expose passing functional transcoders over payloads (both put/get).
  • Health-check utility.
  • Functions return Clojure records.

Opinionated:

  • Non blocking only: Expose only the non-blocking API. Block with deref if you like.
  • Futures instead of callbacks. Futures (and functional chaining) are more composable and less cluttered. If a synchronous behaviour is still desired, the calling code can still deref (@) the returned future object. For a more sophisticated coordination, a variety of control mechanism is supplied by manifold/deferred, or via the library using transcoders or hooks.
  • Follows the method names of the underlying Java APIs.
  • TTLs should be explicit, and developers should think about them. Forces passing a ttl and not use the cluster default.
  • Minimal dependencies.
  • Single client per Aerospike namespace.

Limitations/ caveats

  • Currently supports only single bin records.
  • Does not expose batch/scan operations. Batch reads are supported via get-multi.

TBD

  • Support batch asynchronous APIs.

Usage:

Most of the time just create a simple client (single cluster)

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 instance of ClientEvents. Some useful info is passed in in-order to support metering and to read client configuration. op-start-time is (System/nanoTime) 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 db]
                              (when (:enable-logging? db)
                                (println op-name "success!")))
                            (on-failure [_  op-name op-ex index op-start-time db]
                              (println "oh-no" op-name "failed on index" index)))})]

  (get-single c "index" "set-name"))

Query/Put

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 '[manifold.deferred :as d])
nil
user=> (aero/put c "index" "set-name" 42 1000)
<< … >>
user=> (def f (aero/get-single c "index" "set-name"))
#'user/f
user=> (d/chain (aero/get-single c "index" "set-name")
  #_=>          :ttl
  #_=>          aero/expiry-unix
  #_=>          #(java.time.Instant/ofEpochSecond %)
  #_=>          str
  #_=>          println)
<< … >>
2019-01-10T09:02:45Z

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}

Unix EPOCH TTL

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 UNIX TTL if you want to convert it later to a more standard timestamp.

Testing

Testing is performed against a local Aerospike running in the latest docker

$ sudo docker run -d --name aerospike -p 3000:3000 -p 3001:3001 -p 3002:3002 -p 3003:3003 aerospike
$ lein test

Contributing

PRs are welcome!

License

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close