The ClojureWerkz Blog

News and updates about ClojureWerkz projects

Balagan 1.0.0 Is Released

What is Balagan

Balagan is a tiny Clojure library for data structure transformation inspired by Enlive.

Supported Clojure Versions

Balagan targets Clojure 1.4+, tested against 3 Clojure versions x 2 JDKs on travis-ci.org, and is released under the Eclipse Public License.

Documentation and Examples

Balagan builds on ideas from Enlive. It may help to get familiar with them first.

Let’s say you’re working on a Data Access layer for the application. You have a user entry represented as hash:

1
2
3
4
(def user
  {:name "Alex"
   :birth-year 1990
   :nickname "ifesdjeen"})

Transformation

Now, we can start transforming users the way we want: add, remove fields based on certain conditions.

1
2
3
4
5
(update user
           []                  (add-field :cool-dude true) ;; adds a field :cool-dude with value true
           (new-path [:age])   #(- 2014 (:birth-year %))   ;; explicit adding of a new field, calculated from the existing data
           (new-path [:posts]) #(fetch-posts (:name %))    ;; fetching some related data from the DB
           [:posts :*]         #(update-posts %))       ;; apply some transformations to all the fetched posts, if there are any

Queries

Queries are very similar to how you’d query your data with filter in Clojure:

1
2
3
4
(let [data {:a {:b [{:c 1} {:c 2} {:c 3}]
                :d [{:c 5} {:c 6} {:c 7}]}}]
  (select data  [:* :* even? :c]))
;; => (1 3 5 7)  

Results are returned in the order they’ve been seen in your data structure, however you should be aware of the fact that iterating over the hash in Clojure doesn’t guarantee you order.

Path Queries

Path queries are most useful when you’d like to fire a function against some part of your data (be it processing, database initialization or anything else.

You can also run predicate queries based on your map, for example if you want to configure your database servers from rather big and complex config:

1
2
3
4
5
6
7
8
9
(def conf {:db
           {:redis {:cache  [{:host "host01" :port 1234} {:host "host02" :port 1234}]
                    :pubsub [{:host "host01" :port 1234} {:host "host02" :port 1234}]}}
           :cassandra [{:host "host01"} {:host "host02"}]})

(with-paths conf
        [:db :redis :cache]  configure-redis-cache
        [:db :redis :pubsub] configure-redis-pubsub
        [:db :cassandra]     configure-cassandra)

In this example, configure-redis-cache funciton will receive two arguments: value and path:

1
2
3
4
5
6
7
(defn configure-redis-cache
  [value path]
  (println "Value: " value)
  (println "Path: " path))

;; => Value: [{:host host01, :port 1234} {:host host02, :port 1234}]
;; => Path: [:db :redis :cache]

You can also do wildcard-matching with :*, for example:

1
2
3
4
5
(b/select {:a {:b {:c 1} :d {:c 2}}}
          [:a :* :c] (fn [val path]
                       (if (= path [:a :b :c])
                         (is (= val 1))
                         (is (= val 2)))))

Learn more in the documentation section.

Community

To subscribe for announcements of releases, important changes and so on, please follow @ClojureWerkz on Twitter.

License

Distributed under the Eclipse Public License, the same as Clojure.

The source is available on GitHub. We also use GitHub to track issues.

About the Author

The ClojureWerkz Team.

Meltdown 1.0.0-beta12 Is Released

TL;DR

Meltdown is a Clojure interface to Reactor, an asynchronous programming, event passing and stream processing toolkit for the JVM.

1.0.0-beta12 is a development milestone with minor improvements, and likely the last pre-release version before 1.0.

Changes between 1.0.0-beta11 and 1.0.0-beta12

Reactor Update

Reactor is updated to 1.1.0.RC1.

Changes between 1.0.0-beta10 and 1.0.0-beta11

Set Membereship Selector

clojurewerkz.meltdown.selectors/set-membership is a new selector that matches on element membership in a set:

1
2
3
4
5
(require '[clojurewerkz.meltdown.reactor   :as mr])
(require '[clojurewerkz.meltdown.selectors :as ms)

(let [r   (mr/create)]
  (mr/on r (ms/set-membership #{"white" "red" "blue"} (fn [evt])))

Change log

Meltodwn change log is available on GitHub.

Meltdown is a ClojureWerkz Project

Meltdown is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Elastisch, a Clojure client for ElasticSearch
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Clojure Cassandra client
  • Titanium, a Clojure graph library
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Meltdown, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About the Author

Michael on behalf of the ClojureWerkz Team

Validateur 2.1.0 Is Released

TL;DR

Validateur is a functional validations library inspired by Ruby’s ActiveModel. Validateur 2.1 is a minor feature release.

Changes Between 2.0.0 and 2.1.0

Multi-field Support For Presence Validator

presence-of validator now supports validation over multiple (all or any) fields:

1
2
3
4
5
;; both fields must be non-nil
(vr/presence-of #{:name :msg})

;; either field must be non-nil
(vr/presence-of #{:name :msg} :any true)

Contributed by Radosław Piliszek.

Better ClojureScript Support

Validateur no longer uses crossovers which are deprecated in lein-cljsbuild.

Contributed by Radosław Piliszek.

Full Change Log

Validateur change log is available on GitHub.

Validateur is a ClojureWerkz Project

Validateur is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Monger, a Clojure MongoDB client for a more civilized age
  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • Cassaforte, a Clojure Cassandra client built around CQL
  • Neocons, a client for the Neo4J REST API
  • Welle, a Riak client with batteries included
  • Quartzite, a powerful scheduling library

and several others. If you like Validateur, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About The Author

Michael on behalf of the ClojureWerkz Team

Elastisch 2.0.0-rc1 Is Released

TL;DR

Elastisch is a battle tested, small but feature rich and well documented Clojure client for ElasticSearch. It supports virtually every Elastic Search feature and has solid documentation.

2.0.0-rc1 is a release candidate of Elastisch 2.0, which focuses on the new features in ElasticSearch 1.1 and introduces major API improvements, including a breaking change.

Changes between Elastisch 2.0.0-beta5 and 2.0.0-rc1

Connection/Client As Explicit Argument

Starting with Elastisch 2.0.0-rc1, connection (client) is no longer a shared dynamic var but rather is an explicit argument that relevant API functions accept.

Before the change:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(ns clojurewerkz.elastisch.docs.examples
  (:require [clojurewerkz.elastisch.rest  :as esr]
            [clojurewerkz.elastisch.rest.index :as esi]
            [clojurewerkz.elastisch.rest.document :as esd]))

(defn -main
  [& args]
  (esr/connect! "http://127.0.0.1:9200")
  (let [mapping-types {"person" {:properties {:username   {:type "string" :store "yes"}
                                              :first-name {:type "string" :store "yes"}
                                              :last-name  {:type "string"}
                                              :age        {:type "integer"}
                                              :title      {:type "string" :analyzer "snowball"}
                                              :planet     {:type "string"}
                                              :biography  {:type "string" :analyzer "snowball" :term_vector "with_positions_offsets"}}}}
        doc           {:username "happyjoe" :first-name "Joe" :last-name "Smith" :age 30 :title "Teh Boss" :planet "Earth" :biography "N/A"}]
    (esi/create "myapp2_development" :mappings mapping-types)
    (esd/create "myapp2_development" "person" doc)))

After the change:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(ns clojurewerkz.elastisch.docs.examples
  (:require [clojurewerkz.elastisch.rest  :as esr]
            [clojurewerkz.elastisch.rest.index :as esi]
            [clojurewerkz.elastisch.rest.document :as esd]))

(defn -main
  [& args]
  (let [conn          (esr/connect "http://127.0.0.1:9200")
        mapping-types {"person" {:properties {:username   {:type "string" :store "yes"}
                                              :first-name {:type "string" :store "yes"}
                                              :last-name  {:type "string"}
                                              :age        {:type "integer"}
                                              :title      {:type "string" :analyzer "snowball"}
                                              :planet     {:type "string"}
                                              :biography  {:type "string" :analyzer "snowball" :term_vector "with_positions_offsets"}}}}
        doc           {:username "happyjoe" :first-name "Joe" :last-name "Smith" :age 30 :title "Teh Boss" :planet "Earth" :biography "N/A"}]
    (esi/create conn "myapp2_development" :mappings mapping-types)
    (esd/create conn "myapp2_development" "person" doc)))

Dynamic var reliance has been a major complaint of Clojure users for quite some time and 2.0 is the right time to fix this.

Changes between Elastisch 2.0.0-beta4 and 2.0.0-beta5

Response Helpers Compatible With ES 1.1

clojurewerkz.elastisch.rest.response/created? and clojurewerkz.elastisch.native.response/created? were adapted for recent ES releases.

Contributed by Oliver McCormack (The Climate Corporation).

ElasticSearch Client Update

ElasticSearch client has been upgraded to 1.1.1.

Changes between Elastisch 2.0.0-beta3 and 2.0.0-beta4

Options As Maps

Elastisch has tranditionally accepted options as (pseudo) keywrod arguments, e.g.

1
(doc/search index-name mapping-type :query (q/term :biography "say"))

Starting with 2.0.0-beta4, passing a single map of arguments is now also supported by nearly all document, index, admin and percolation functions:

1
(doc/search index-name mapping-type {:query (q/term :biography "say")})

As a new design rule, all new API elements (e.g. aggregations) will accept a single map of options.

GH issue: #59.

Percolation of Existing Documents (REST API)

REST API client now supports percolation of existing documents:

1
2
3
(require '[clojurewerkz.elastisch.rest.percolation :as pcl])

(pcl/percolate-existing "articles" "article" "123")

Changes between Elastisch 2.0.0-beta2 and 2.0.0-beta3

ElasticSearch Client Update

ElasticSearch client has been upgraded to 1.1.0.

Clojure 1.6

Elastisch now depends on org.clojure/clojure version 1.6.0. It is still compatible with Clojure 1.4 and if your project.clj depends on a different version, it will be used, but 1.6 is the default now.

Type Exists Operation

types-exists support in both rest and native clients:

1
2
3
(require '[clojurewerkz.elastisch.rest.index :as esi])

(esi/type-exists? "an-index" "a-type")

Contributed by Halit Olali.

Changes between Elastisch 2.0.0-beta1 and 2.0.0-beta2

(Improved) Aggregation Support

Elastisch 2.0 features multiple convenience functions for working with ElasticSearch aggregations.

clojurewerkz.elastisch.aggregation is a new namespace that contains helper functions that produce various types of aggregations. Just like clojurewerkz.elastisch.query, all of the functions return maps and are optional.

clojurewerkz.elastisch.rest.response/aggregations-from is a new function that returns aggregations from a search response:

1
2
3
4
5
6
7
8
9
10
11
12
(require '[clojurewerkz.elastisch.rest.document :as doc])
(require '[clojurewerkz.elastisch.query :as q])
(require '[clojurewerkz.elastisch.aggregation :as a])
(require '[clojurewerkz.elastisch.rest.response :refer [aggregations-from]])

(let [index-name   "people"
        mapping-type "person"
        response     (doc/search index-name mapping-type
                                 :query (q/match-all)
                                 :aggregations {:min_age (a/min "age")})
        agg          (aggregation-from response :min_age)]
    (is (= {:value 22.0} agg)))

Aggregations support is primarily focused on REST client at the moment.

clj-http Update

clj-http dependency has been upgraded to version 0.9.1.

Changes between Elastisch 1.4.0 and 2.0.0-beta1

ElasticSearch 1.0 Compatibility

Main goal of Elastisch 2.0 is ElasticSearch 2.0 compatibility. This includes minor API changes (in line with ElasticSearch 1.0 API and terminology changes) and moderate internal modifications.

Support for cluster nodes stats and info REST APIs

clojureworkz.elastisch.rest.admin/nodes-info and clojureworkz.elastisch.rest.admin/nodes-stats are new administrative functions that provide access to ElasticSearch cluster stats and node info.

Examples:

1
2
3
4
5
6
7
8
9
(require '[clojurewerkz.elastisch.rest.admin :as admin])

(admin/nodes-stats)
(admin/nodes-stats :nodes "_all")
(admin/nodes-stats :nodes ["node1" "node2"] ["indices" "os" "plugins"])

(admin/nodes-info)
(admin/nodes-info :nodes "_all")
(admin/nodes-info :nodes ["node1" "node2"] ["indices" "os" "plugins"])

See ElasticSearch nodes stats documentation, nodes info page, and node specification page for more info.

Contributed by Joachim De Beule.

Support for _cluster/state REST API

Added (clojureworkz.elastisch.rest.admin/cluster-state & {:as params})

Examples:

1
2
3
4
(require '[clojurewerkz.elastisch.rest.admin :as admin])

(admin/cluster-state)
(admin/cluster-state :filter_nodes true)

See ElasticSearch documentation for more info.

Contributed by Joachim De Beule.

Support for _cluster/health REST API

Added (clojureworkz.elastisch.rest.admin/cluster-health & {:as params})

Example:

1
2
3
4
5
6
(require '[clojurewerkz.elastisch.rest.admin :as admin])

(admin/cluster-health)
(admin/cluster-health :index "index1")
(admin/cluster-health :index ["index1","index2"])
(admin/cluster-health :index "index1" :pretty true :level "indices")

See ElasticSearch documentation for more info.

Contributed by Joachim De Beule.

Support for analyze in REST API client

Added (doc/analyze text & {:as params})

See ElasticSearch documentation for more info.

Examples:

1
2
3
4
5
6
7
(require '[clojurewerkz.elastisch.rest.document :as doc])

(doc/analyze "foo bar baz")
(doc/analyze "foo bar baz" :index "some-index-name")
(doc/analyze "foo bar baz" :analyzer "whitespace")
(doc/analyze "foo bar baz" :tokenizer "keyword" :filters "lowercase")
(doc/analyze "foo bar baz" :index "some-index-name" :field "some-field-name")

Contributed by Joachim De Beule

Query String Escaping

clojurewerkz.elastisch.query/query-string accepts a new option, :escape-with, which is a function that performs escaping of special characters in query string queries.

By default clojurewerkz.elastisch.escape/escape-query-string-characters is used.

Contributed by Ben Reinhart (Groupon).

ElasticSearch Native Client Upgrade

Elastisch now depends on ElasticSearch native client version 1.0.1.

clj-http Update

clj-http dependency has been upgraded to version 0.9.0.

Full Change Log

Elastisch change log is available on GitHub.

Thank You, Contributors

Kudos to Halit Olali, shmish111, and Richie Vos for contributing to the 2.0 release.

Elastisch is a ClojureWerkz Project

Elastisch is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Clojure Cassandra client
  • Titanium, a Clojure graph library
  • Neocons, a client for the Neo4J REST API
  • Welle, a Riak client with batteries included
  • Quartzite, a powerful scheduling library

and several others. If you like Elastisch, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About the Author

Michael on behalf of the ClojureWerkz Team

Neocons 3.0.0-rc1 Is Released

TL;DR

Neocons is a feature rich idiomatic Clojure client for the Neo4J REST API.

3.0.0-rc1 is a release candidate. It has one major breaking API change compared to 2.0.x: every function now takes a connection record as an explicit argument instead of relying on a dynamic var.

Changes between Neocons 2.0.0 and 3.0.0

Breaking Change: Explicit Connection Argument

Neocons no longer uses a dynamic var to hold the state of the connection. This leads to significant changes to the API as the connection has to be passed to functions. The position of the connection argument is always the first argument for the sake of consistency:

1
2
3
4
5
6
7
8
9
10
11
(require '[clojurewerkz.neocons.rest :as nr])
(require '[clojurewerkz.neocons.rest.nodes :as nn])

;; with Neocons 2.0

(nr/connect! "http://localhost:7476/db")
(nn/create {:url "http://clojurewerkz.org/"})

;; with Neocons 3.0
(let [conn (nr/connect "http://localhost:7476/db")]
  (nn/create conn {:url "http://clojurewerkz.org/"}))

Additionally connect! function in clojurewerkz.neocons.rest no longer exists. This has been replaced by function connect in clojurewerkz.neocons.rest. The connect function has the same arguments as the connect! function only it returns a Connection record.

The Connection record has a key called :options which can be used to pass additional parameters to be used by clj-http like debug.

Contributed by Rohit Aggarwal.

Clojure 1.6

Neocons now depends on org.clojure/clojure version 1.6.0. It is still compatible with Clojure 1.4 and if your project.clj depends on a different version, it will be used, but 1.6 is the default now.

Cheshire 5.3

Neocons now uses Cheshire 5.3.

clj-http upgraded to 0.9.1

Neocons now uses clj-http 0.9.1.

Neo4J 2.0 Index Creation Fix

Neocons will now use a key name accepted by Neo4J 2.0.0 GA and later version when creating indexes.

Contributed by Rohit Aggarwal.

Change Log

We encourage all users to give this version a try.

Neocons change log is available on GitHub.

Documentation Updates

Neocons documentation has been updated to cover the new API.

Thank You, Contributors

We’d like to thank Rohit Aggarwal for single-handedly doing all the work in Neocons 3.0. Contributors like Rohit is why open source software works as well as it does.

Neocons is a ClojureWerkz Project

Neocons is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Cassandra client built around CQL 3
  • Quartzite, a powerful scheduling library

and several others. If you like Neocons, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

Michael on behalf of the ClojureWerkz Team

Major Breaking Public API Changes Coming in Our Projects

TL;DR

If you use a ClojureWerkz project (or two), please beware that libraries that rely on dynamic vars (e.g. Monger or Elastisch) will undergo a major API revision soon. We generally try to keep things as backwards compatible as possible but this is the right thing to do.

Everything Should Be Made As Easy As Possible

The ClojureWerkz philosophy has always been: easy matters. With all the focus on simplicity in the Clojure community, ease of use is often seen as a secondary concern or outright ignored.

To paraphrase Albert Einstein, “everything should be made as easy as possible”. This is why some of our projects (Monger, Elastisch, Neocons, Cassaforte) historically relied on a shared dynamic var for some commonly global state (e.g. database connection).

This makes it very easy to get started with the project and (we believe) helped some people adopt Clojure faster and with less frustration.

…But Not Easier

Unfortunately, the kind of problems you face early on in software engineering are not exactly the same as problems that arise as your project grows.

A lot of the problems have to do with scale but no the “bajillion request per second” kind. Rather, it’s about scaling your development team, product features, and making things operationally sane.

This is where some of the library aspects that are incredibly valuable to complete beginners are not very valuable or outright annoying to more experienced teams.

Overreliance on dynamic vars is by far the most common complaint we hear about Elastisch, Monger and so on. Over time we introduced alternative APIs (“monger.multi”) or overloaded function arities to make it easier for developers to use multiple connections when needed. But the complaints did not end. We need to act more boldly and we will.

Breaking Public APIs

So here’s the news: next versions of Monger, Elastisch, Neocons, and Cassaforte will make db/connection/client a mandatory explicit argument across the entire public API.

In other words, instead of

1
(a-fn arg1 arg2)

you will have to use

1
(a-fn conn arg1 arg2)

To demonstrate this with a snippet of code that uses Elastisch, before the change:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(ns clojurewerkz.elastisch.docs.examples
  (:require [clojurewerkz.elastisch.rest  :as esr]
            [clojurewerkz.elastisch.rest.index :as esi]
            [clojurewerkz.elastisch.rest.document :as esd]))

(defn -main
  [& args]
  (esr/connect! "http://127.0.0.1:9200")
  (let [mapping-types {"person" {:properties {:username   {:type "string" :store "yes"}
                                              :first-name {:type "string" :store "yes"}
                                              :last-name  {:type "string"}
                                              :age        {:type "integer"}
                                              :title      {:type "string" :analyzer "snowball"}
                                              :planet     {:type "string"}
                                              :biography  {:type "string" :analyzer "snowball" :term_vector "with_positions_offsets"}}}}
        doc           {:username "happyjoe" :first-name "Joe" :last-name "Smith" :age 30 :title "Teh Boss" :planet "Earth" :biography "N/A"}]
    (esi/create "myapp2_development" :mappings mapping-types)
    (esd/create "myapp2_development" "person" doc)))

After the change:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(ns clojurewerkz.elastisch.docs.examples
  (:require [clojurewerkz.elastisch.rest  :as esr]
            [clojurewerkz.elastisch.rest.index :as esi]
            [clojurewerkz.elastisch.rest.document :as esd]))

(defn -main
  [& args]
  (let [conn          (esr/connect "http://127.0.0.1:9200")
        mapping-types {"person" {:properties {:username   {:type "string" :store "yes"}
                                              :first-name {:type "string" :store "yes"}
                                              :last-name  {:type "string"}
                                              :age        {:type "integer"}
                                              :title      {:type "string" :analyzer "snowball"}
                                              :planet     {:type "string"}
                                              :biography  {:type "string" :analyzer "snowball" :term_vector "with_positions_offsets"}}}}
        doc           {:username "happyjoe" :first-name "Joe" :last-name "Smith" :age 30 :title "Teh Boss" :planet "Earth" :biography "N/A"}]
    (esi/create conn "myapp2_development" :mappings mapping-types)
    (esd/create conn "myapp2_development" "person" doc)))

The change is quite small but both radical enough to make upgrading harder for some people and radically simplify app architecture for others (no more shared state you have to work around all the time).

Two libraries are already updated: Elastisch 2.0 and Neocons 3.0.

Thank You, Contributors

We’d like to thank Rohit Aggarwal for making all the changes described above for Neocons 3.0. Contributors like Rohit is why open source software works as well as it does.

About the Author

Michael on behalf of the ClojureWerkz Team

Meltdown 1.0.0-beta10 Is Released

TL;DR

Meltdown is a Clojure interface to Reactor, an asynchronous programming, event passing and stream processing toolkit for the JVM.

1.0.0-beta10 is a development milestone with minor improvements.

Changes between 1.0.0-beta9 and 1.0.0-beta10

Reactor Update

Reactor is updated to 1.1.0.M3.

2-arity of clojurewerkz.meltdown.reactor/on is Removed

Reactor 1.1.0.M3 no longer supports default key (selector), so 2-arity of clojurewerkz.meltdown.reactor/on was removed.

Clojure 1.6

Meltdown now depends on org.clojure/clojure version 1.6.0. It is still compatible with Clojure 1.4 and if your project.clj depends on a different version, it will be used, but 1.6 is the default now.

Changes between 1.0.0-beta8 and 1.0.0-beta9

Consumer and Selector Introspection

clojurewerkz.meltdown.selectors/selectors-on is a new function that returns a list of selectors registered on a reactor:

1
2
3
4
5
6
(require '[clojurewerkz.meltdown.reactor   :as mr])
(require '[clojurewerkz.meltdown.selectors :as ms :refer [$])

(let [r   (mr/create)]
  (mr/on r ($ "a.key) (fn [evt]))
  (ms/selectors-on r))

clojurewerkz.meltdown.consumers/consumer-count is a new function that returns a number of consumers registered on a reactor:

1
2
3
4
5
6
7
(require '[clojurewerkz.meltdown.reactor   :as mr])
(require '[clojurewerkz.meltdown.selectors :refer [$])
(require '[clojurewerkz.meltdown.consumers :as mc])

(let [r   (mr/create)]
  (mr/on r ($ "a.key) (fn [evt]))
  (mc/consumer-count r))

Change log

Meltodwn change log is available on GitHub.

Meltdown is a ClojureWerkz Project

Meltdown is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Elastisch, a Clojure client for ElasticSearch
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Clojure Cassandra client
  • Titanium, a Clojure graph library
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Meltdown, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About the Author

Michael on behalf of the ClojureWerkz Team

Elastisch 2.0.0-beta4 Is Released

TL;DR

Elastisch is a battle tested, small but feature rich and well documented Clojure client for ElasticSearch. It supports virtually every Elastic Search feature and has solid documentation.

2.0.0-beta4 is a preview release of Elastisch 2.0, which focuses on the new features in ElasticSearch 1.0 and 1.1 as well as some API refinements.

Changes between Elastisch 2.0.0-beta3 and 2.0.0-beta4

Options As Maps

Elastisch has tranditionally accepted options as (pseudo) keywrod arguments, e.g.

1
(doc/search index-name mapping-type :query (q/term :biography "say"))

Starting with 2.0.0-beta4, passing a single map of arguments is now also supported by nearly all document, index, admin and percolation functions:

1
(doc/search index-name mapping-type {:query (q/term :biography "say")})

As a new design rule, all new API elements (e.g. aggregations) will accept a single map of options.

GH issue: #59.

Percolation of Existing Documents (REST API)

REST API client now supports percolation of existing documents:

1
2
3
(require '[clojurewerkz.elastisch.rest.percolation :as pcl])

(pcl/percolate-existing "articles" "article" "123")

Changes between Elastisch 2.0.0-beta2 and 2.0.0-beta3

ElasticSearch Client Update

ElasticSearch client has been upgraded to 1.1.0.

Clojure 1.6

Elastisch now depends on org.clojure/clojure version 1.6.0. It is still compatible with Clojure 1.4 and if your project.clj depends on a different version, it will be used, but 1.6 is the default now.

Type Exists Operation

types-exists support in both rest and native clients:

1
2
3
(require '[clojurewerkz.elastisch.rest.index :as esi])

(esi/type-exists? "an-index" "a-type")

Contributed by Halit Olali.

Full Change Log

Elastisch change log is available on GitHub.

Thank You, Contributors

Kudos to Halit Olali, shmish111, and Richie Vos for contributing to this release.

Elastisch is a ClojureWerkz Project

Elastisch is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Clojure Cassandra client
  • Titanium, a Clojure graph library
  • Neocons, a client for the Neo4J REST API
  • Welle, a Riak client with batteries included
  • Quartzite, a powerful scheduling library

and several others. If you like Elastisch, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About the Author

Michael on behalf of the ClojureWerkz Team

Langohr 2.9.0 Is Released

TL;DR

Langohr is a small Clojure RabbitMQ client.

2.9.0 is a minor feature release.

Changes between Langohr 2.8.x and 2.9.0

Configurable Default and Per-Operation Options in HTTP API Client

Most HTTP API client functions now have an additional optional arguments, which is a map of options passed to clj-http functions. This lets you fine tune certain HTTP requests as needed.

In addition, langohr.http/connect! now accepts one more argument which serves as default HTTP client options merged with the options provided per langohr.http function call:

1
2
3
4
5
6
7
8
9
10
11
12
(require '[langohr.http :as hc])

;; non-20x/30x statuses will now throw exceptions
(hc/connect! "http://127.0.0.1:15673" "guest" "guest" {:throw-exceptions true})

;; disable throwing exceptions for an individual operation,
;; because 404 is an expected HTTP response in this case
(hc/vhost-exists? "myapp-production" {:throw-exceptions false})
;= false

;; disabling peer verification for HTTPS requests
(hc/connect! "http://127.0.0.1:15673" "guest" "guest" {:insecure? true})

Thread Factory Customization

It is now possible to customize a java.util.concurrent.ThreadFactory used by Langohr connections. The factory will be used to instantiate all threads created by the client under the hood.

The primary use case for this is running on Google App Engine which prohibits direct thread instantiation and requires apps to use thread manager (or thread factory) from GAE SDK instead.

To provide a custom thread factory, pass it as :thread-factory to langohr.core/connect. To reify a thread factory with a Clojure function, use langohr.core/thread-factory-from:

1
2
3
4
5
6
(require '[langohr.core :as lc])

(let [tf (lc/thread-factory-from
            (fn [^Runnable r]
              (Thread. r)))]
  (lc/connect {:thread-factory tf}))

com.rabbitmq.client.TopologyRecoveryException is Used

Langohr now uses com.rabbitmq.client.TopologyRecoveryException instead of reinventing its own exception to indicate topology recovery failure.

RabbitMQ Java Client Compatibility

A few RabbitMQ Java client interface compatibility issues are resolved.

Change Log

Langohr change log is available on GitHub.

Langohr is a ClojureWerkz Project

Langohr is part of the group of libraries known as ClojureWerkz, together with

  • Elastisch, a minimalistic well documented Clojure client for ElasticSearch
  • Cassaforte, a Clojure Cassandra client built around CQL 3.0
  • Monger, a Clojure MongoDB client for a more civilized age
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Langohr, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About The Author

Michael on behalf of the ClojureWerkz Team

Langohr 2.8.1 Is Released

TL;DR

Langohr is a small Clojure RabbitMQ client.

2.8.1 is a minor feature release.

Changes between Langohr 2.7.x and 2.8.1

Client-side Channel Flow Removed

langohr.channel/flow and langohr.channel/flow? were removed. Client-side flow control has been deprecated for a while and was removed in RabbitMQ Java client 3.3.0.

RabbitMQ Java Client Upgrade

RabbitMQ Java client dependency has been updated to 3.3.0.

Clojure 1.6 By Default

Langohr now depends on org.clojure/clojure version 1.6.0. It is still compatible with Clojure 1.4 and if your project.clj depends on a different version, it will be used, but 1.6 is the default now.

We encourage all users to upgrade to 1.6, it is a drop-in replacement for the majority of projects out there.

langohr.http/protocol-ports

langohr.http/protocol-ports is a new function that returns a map of protocol names to protocol ports. The protocols are listed with langohr.http/list-enabled-protocols.

Change Log

Langohr change log is available on GitHub.

Langohr is a ClojureWerkz Project

Langohr is part of the group of libraries known as ClojureWerkz, together with

  • Elastisch, a minimalistic well documented Clojure client for ElasticSearch
  • Cassaforte, a Clojure Cassandra client built around CQL 3.0
  • Monger, a Clojure MongoDB client for a more civilized age
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Langohr, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About The Author

Michael on behalf of the ClojureWerkz Team