-
add qbits.alia/component module This adds a https://github.com/stuartsierra/component for alia with single/multicluster capabilities and also a query registry that encapsulates query level information/state (prepared queries).
Docs will come for this, but if you feel adventurous you can already try it based on the information you'd find in the related PR:
Thanks @pyr for the work on this.
On a side not this is the last release with the alia-all package, in the near future there will be a re-do on the way we manage the modules and alia-all will go away. That simply means you will have to pick and choose what you need/want, which is a better default.
- add qbits.alia/prepare-async
-
kill deprecated modules: eao.uuid, nippy
-
bump clojure, java-driver, core.async, test.check
-
make default seq result-set more lightweight: it's no longer lazy with a cell per row, it's now chunked (default clj behavior)
- update tardis
- Use datastax compatibility layer to inteact with one of guava deprecated utility
- Added :max-requests-per-connection :queue-size :pool-timeout-millis to cluster pooling options
- Use java-driver 3.3.0 driver-core/CHANGELOG
-
use clojure 1.9 alpha17
-
no longer depend on qbits/spex
-
catch Exception not Throwable
-
qbits.alia/execute now takes an optional
:channel
, kill noop close! on promise-chan -
bump manifold dependency
- use clojure 1.9 alpha16 (breaking changes, see: https://groups.google.com/forum/#!topic/clojure/nB4qnDNGS2A)
- Allow to pass most policies as EDN data (see cluster docstring) instead of java instances
- Use java-driver 3.2.0 driver-core/CHANGELOG
- alia-async: depend on core.async 0.3.442
- alia-async: depend on core.async 0.3.441
- Use java-driver 3.1.4 driver-core/CHANGELOG
- alia-async: depend on core.async 0.3.436
codec: simplify handing out to map->Record constructors #73 - Thanks to @pyr for the fix
Remove all traces of blocking IO in
qbits.alia-manifold/execute-buffered
. It now pages manually as the
consumer takes values from the stream (as long as the stream is open).
Thanks to @mccraigmccraig this.
Remove all traces of blocking IO in execute-chan-buffered
,
it now pages manually as the consumer takes values from the chan.
You can also now interup streaming/paging by async/close!
ing the
channel returned by execute-chan-buffered
.
** Breaking changes **
The way the internal codec works has changed. Previously we had one
protocol, qbits.alia/PCodec
that included both decoding and
encoding function. Now "Codecs" are first class, they can be passed
a :codec
option to execute/bind functions and can have custom
behavior/state, as a result we are no longer bound to one global
codec registry and can allow multiple strategies.
A codec is now a map/record that contains 2 fields/keys, :decoder
:encoder
, that have functions as values. The
qbits.alia.codec/default
codec for instance, which is the port of
the old one, is a record implementing a protocol with the equivalent
of the previous strategies. You can see it here:
https://github.com/mpenet/alia/blob/feature/codec-alt/modules/alia/src/qbits/alia/codec/default.clj
It can also serve as a base to compose other codecs using the same functions, using clojure.core/extend for instance (more on this later).
So why doing this? This opens the door to new codecs with new behavior with potentially state. That way we can for instance implement specialised codecs that will know how to automaticaly decode/encode keyspace bound UDTs as record instance, or as a deftype, or whatever you'd like really. And mix and match these codecs in your app, in the same jvm without causing clashes or causing performance degradation because you are doing something fancy in your codec.
We will include by default one such custom implementation (other than the default), an UDT aware codec that does just what I described before: translating UDT values to record instance of chosen type at decoding time.
For most users who extended PCodec before, the changes should be minimal: You just need to extend the default codec protocols (with an S, we separated encoding decoding, to avoid creating "identity" functions for nothing when you just care about one or the other) with your functions/types
Here is an example with joda-time https://github.com/mpenet/alia/blob/feature/codec-alt/modules/alia-joda-time/src/qbits/alia/codec/joda_time.clj
Another nice thing this allows us to do is to create high
performance codecs that do the minimum {:encoder identity :decoder identity}
), or create specialized ones where everything is inlined
(ex in defrecord body) but closed.
In terms of performance the default codec is identical as the old one, since it's essentially the same code.
** Non Breaking changes **
- Updated specs to match new api
- Backported some of Datastax changes to the ssl cluster options
- Updgrade to latest dse
** Hayt **
If you're using it, upgrade to the latest version, the performance improved significantly in the latest releases.
-
Add support for "custom row generators": If you don't care about having rows returned as keywordized maps you can skip what comes next.
All "execute" calls in alia's API can now take an additional option:
row-generator
We now have aqbits.alia.codec/RowGenerator
protocol that opens how rows are decoded per query.(defprotocol RowGenerator (init-row [this] "Constructs a row base") (conj-row [this r k v] "Adds a entry/col to a row") (finalize-row [this r] "\"completes\" the row"))
You can this way generate rows as vectors, or records or deftype instances or anything you'd like really. It kind of follows the way transient work, it's a 3 operation definition ("setup" row bag, "add" col to row bag, "close" row bag).
By default there are 3 generators defined:
qbits.alia.codec/row-gen->map
: the defaultqbits.alia.codec/row-gen->vector
: builds a vector of valuesqbits.alia.codec/row-gen->record
: that one is a function that takes a map->foo like constructor.
And feel free to implement your own.
As a result the
key-fn
option has been removed, but I don't think anybody used it (at least in OSS). But that's easy to restore via a custom generator if you need to (it's a copy of row-gen->map without a keyword call):(def row-gen->map "Row Generator that stringy map instances" (reify RowGenerator (init-row [_] (transient {})) (conj-row [_ row k v] (assoc! row k v)) (finalize-row [_ row] (persistent! row))))
- depends on clojure 1.9.0-alpha12
- Merged alia-spec into master and added instrumentation to tests
- alia-manifold: execute-chan-buffered will now work like with alia-async version, respect buffer size and handle backpressure accordingly. Thanks @mccraigmccraig for spotting the issue and providing the fix.
- depends on alia-manifold 3.1.4
- Use java-driver 3.1.0 driver-core/CHANGELOG
- Use java-driver 3.0.3 driver-core/CHANGELOG
- resolves #59 timestamps not binding appropriately for named parameters #60
- Use java-driver 3.0.2 driver-core/CHANGELOG
- Fix some cluster options errors with adresstranslator and timestampgenerator
- Use java-driver 3.0.1 driver-core/CHANGELOG
- SSLOptions in
alia
main module: #55 @blak3mill3r fixed ssl options handling in cluster builder
- kill stray qbits.alia file in qbits.alia.async causing major breakage
- remove aliases to async functions since it acutally doesn't work
(you can import them from
qbits.alia.async
).
Breaking changes (package/dependency level, not code)
-
Alia was split into separate libaries to allow more flexible builds, lighter dependencies, better aot'isability and also make it ok to add more exotic features without adding weight on the core (an upcoming Component, optional schemas for cluster options, direct linking, etc).
If you don't really care and want the whole package like before, you can just change your dependencies to
[cc.qbits/alia-all "3.1.0"]
. If you were usingexecute-chan
orexecute-chan-buffered
, you will now find these 2 function inqbits.alia.async
Alia was split like this:
alia
: minimal core of the driver (whithout core.async/manifold/custom codec extensions)alia-async
: core.async interface (qbits.alia/execute-chan
,qbits.alia/execute-chan-buffered
)alia-manifold
: manifold async interaface (qbits.alia.manifold/*
same as before)alia-eaio-uuid
: eaio.uuid codec extensionalia-joda-time
: joda-time codec extensionalia-nippy
: the Nippy codec extension
They are located in ./modules. The version numbers will always match the core lib,
alia
to avoid confusions.A simple example, if you only want to use the core and the core.async extenstion you can just add these to your dependencies:
[cc.qbits/alia "3.1.2"] [cc.qbits/alia-async "3.1.2"]
-
Use java-driver 3.0.0 (final) driver-core/CHANGELOG
-
Simple statements can now take named placeholders (same as prepared):
(execute session "SELECT * FROM foo WHERE bar = :bar-value" {:values {:bar-value "something"}})`
- Add per query
read-timeout
via execute options
Breaking change
-
Hayt
is not included by default anymore. You can include it manually in your dependencies, then simply loadingqbits.hayt
in the namespace(s) where you use it with alia and will extend the appropriate protocol and provide total backward compatibility. (I had to do this to accomodate users which had dependency conflicts with hayt (and were not using it)).tldr: add
[cc.qbits/hayt "3.0.0"]
in your deps if/when you use it.
- Use java-driver 3.0.0-rc1 driver-core/CHANGELOG
-
typo translater -> translator (from upstream)
-
remove hayt query caching, let this to the end user to manage if wanted
More infos here about using 3.x: https://github.com/datastax/java-driver/tree/3.0/upgrade_guide
- Correct cassandra-driver-dse exclusions see #47
- Use java-driver 2.1.9 driver-core/CHANGELOG
-
Use latest core.async: as a result
qbits.alia/execute-chan
now returns a core.async/promise-chan. -
Update core.memoize dependency
- Use java-driver 2.1.8 driver-core/CHANGELOG
-
Respect nullability of row cells: previously a Boolean column would be False when no value was set, a Long would always default to 0 and so on. This differed from cqlsh and what's general expected and was a side effect of the java API available at the time the decoding code was written.
-
Handle custom decoding in deeply nested datastructures via PCodec protocol #45. It's on by default but it is possible to turn this off by extending PCodec protocol for Map, List, Set, TupleValue, UDTValue to just be "identity".
-
ResultSet decoding is now done via a protocol that implements both seq() and IReduceInit(), the former would return an unchunked lazy seq (it's the detault, same as previous versions, it's equivalent to passing
{:result-set-fn seq}
to execute), and the later would you to get a reducible for instance if you pass#(into [] %)
as a:result-set-fn
, which is eager and cheaper.IReduceInit
is 1.7+ only, hence the new requirement. -
Via
:result-set-fn
you can also reach ExecutionInfos from the rs (which was previously always set as metadata to rs) by calling qbits.codec/execution-info on the argument passed to your function, from there you could for instance log the information returned. -
Breaking:
:string-keys?
is removed in favor of:key-fn
-
drop :exception-info metadata on result-set
-
prevent calls to ResultSet.one() when not needed (true fire and forget)
- manifold interface, fix NPE when missing success or error handler passed to manifold/on-realized
-
All enum taking fns will now reject invalid values and throw if something weird is supplied
-
row decoding is now truly lazy, skipping clojure chunking and respecting fetch-size more accurately (especially important for execute-chan-buffered).
-
invalid udt/tuple encoders now throw if supplied an invalid type name
Breaking changes
- UDT field names are now decoded as clojure Keywords instead of strings
** New Features **
-
qbits.alia/tuple-encoder
andqbits.alia/udt-encoder
: add Tuple and UDT encoder functions to be used with prepared statements. They both return a function that can be used to encode tuple/udt of the selected type. ex:(let [user (qbits.alia/udt-encoder session :user)] (execute session user-insert-prepared-stmt {:values [(user {:id "foo" :age 10})]}))
Internal encoding of values respects the main encoder (
qbits.codec.PCodec
), that means if you extended it for joda time or your own types for this should work transparently even if your UDT are deeply nested.
- fix decoding of tuple/udt values when NULL (issue #40)
- Meh, Broken deploy
-
Add support to named placeholders in prepared statements (:value can take a map that will either match placeholders of column name values) - Thanks to @d-t-w
-
Add
qbits.alia/batch
-
Use shadded Netty dependency (allows to use another netty version in your code if needed) - Thanks to @d-t-w
-
Remove deprecated Lamina interface
-
Improve decoding performance
-
More uniform exception handling in async modes (all exceptions are returned in chan/deferred/function depending on the context)
- Fix possible chan leaks/flow break in async error handling (thanks to @d-t-w). See issue #29 for details.
- fix some bugs in the nippy encoder
- Add simple callback based alia/execute-async (takes :success and/or :error functions via option map)
-
Use java-driver 2.1.6 driver-core/CHANGELOG
-
adds cluster options and related utils for: speculative execution, address-translater, cluster-name, netty-options, timestamp-generator, max-schema-agreement-wait-seconds
-
new execute* options for
:paging-state
andidempotent?
- Use latest Hayt https://github.com/mpenet/hayt/blob/master/CHANGELOG.md
-
Improve joda-time codec for java.util.Date decoding from data returned by cassandra
-
Adds experimental nippy codec with various modes:
- by calling (set-nippy-collection-encoder! nippy-opts) and (set-nippy-collection-decoder! nippy-opts) all collections passed to alia will be stored as ByteBuffer and decoded back to clj collections when queried. This is fast, but breaks cassandra native collections encoding in prepared statements. If you need to handle both the other mode is for you.
- the other mode requires you to call qbits.alia.codec.nippy/serializable! on the data you want to have serialized. All bytebuffers returned by cassandra will be considered as nippy data.
If you need more fine grained control you are be better off calling thaw/freeze manually on a per column basis in your app.
- Add decode function to PCodec protocol to allow custom decoding (ex joda)
- allow to specifiy timestamp via query options
- fix encoding error in joda-time codec
- remove log4j properties file used for debugging locally that sneaked in!
- Use java-driver 2.1.5 driver-core/CHANGELOG
-
improve resource use and performance in async mode by running the put! in the io thread (since it's async anyway), not using an external thread pool. You can still pass :executor to the execute-* call and override this behavior.
-
remove now useless qbits.knit dependency
- bump hayt dependency (c* 2.1+ udt support)
- add optional manifold
interface, see
qbits.alia/manifold
- add support for Kerberos (via
:kerberos?
option) & TLS by adding:ssl-options
map argument support, it now accepts an SSLOption instance (as before) or a map of:keystore-path
:keystore-password
:cipher-suites
.
- Use java-driver 2.1.4 driver-core/CHANGELOG
- Use java-driver 2.1.3 driver-core/CHANGELOG
- Use java-driver 2.1.2 driver-core/CHANGELOG
- Use java-driver 2.1.1 driver-core/CHANGELOG
- Use latest Hayt https://github.com/mpenet/hayt/blob/master/CHANGELOG.md
- Lamina async interface is deprecated and moved in a separate ns. If you sill use it, you'll need to bring lamina as a dependency to your project.
- Allow execution of parameterized statements with their values in 1 roundtrip.
(execute session "select * from foo where bar = ?;" {:values ["baz"]})
(execute session (select :foo (where [[= :bar ?]])) {:values ["baz"]})
...
- Full support for CQL UDT & TUPLE: Auto-decoding of CQL Tuple and User Data Types. You can insert them using literals in both prepared statements and raw queries. See article about this here and there.
- Use java-driver 2.1.0 driver-core/CHANGELOG
- Update to latest core.async
- Empty List now returns [] instead of nil, to match Map and Set types
- Update to latest Lamina (manifold support), core.async, core.cache, clj-time
- Use java-driver 2.1.0-rc1 driver-core/CHANGELOG
-
Use java-driver 2.0.3 driver-core/CHANGELOG
-
Use latest core.async
- Add
execute-chan-buffered
: Allows to execute a query and have rows returned in aclojure.core.async/chan
. Every value in the chan is a single row. By default the query:fetch-size
inherits from the cluster setting, unless you specify a different:fetch-size
at query level and the channel is a regularclojure.core.async/chan
, unless you pass your own:channel
with its own sizing caracteristics.:fetch-size
dicts the "chunking" of the rows returned, allowing to "stream" rows into the channel in a controlled manner.
The name of this fn could be subject to change in future versions.
- Use java-driver 2.0.2 driver-core/CHANGELOG
Breaking changes -> API cleanup, performance, better composability
- We got rid of all the dynamic vars and related functions/macros
(
set-*
,with-*
) - All
execute*
functions, as well asprepare
, now require an explicit session argument (it was optional before), options are now a map instead of kwargs cluster
now takes a map instead of hosts + kwargs- Performance improvement (as a result of the previous changes)
- No longer leaks the default-executor for async, it will be initialized lazily the first time it's needed (if at all)
The next release will likely be 2.0 final, and the API will be stable from now on.
- Breaking changes Use latest Hayt https://github.com/mpenet/hayt/blob/master/CHANGELOG.md
- Use java-driver 2.0.1 driver-core/CHANGELOG
- Use java-driver 2.0.0 final driver-core/CHANGELOG
- Use java-driver 2.0.0-rc3 driver-core/CHANGELOG
- Use Lamina 0.5.2, fixed repl reloading see ztellman/lamina#82
- Add QueryOptions com.datastax.driver.core.QueryOptions support at cluster level
-
Add Statement.setFetchSize - Thanks @coltnz
-
Add serial consistency support
- Use newest core.async
- Use java-driver 2.0.0-rc2 driver-core/CHANGELOG
- Use latest core.async
- Use latest Hayt https://github.com/mpenet/hayt/blob/master/CHANGELOG.md
-
Use java-driver 2.0.0-rc1 driver-core/CHANGELOG
-
keyword cql-values are no longer encoded as strings (you have to manually handle this), since keywords will be used as named bind markers in the future.
-
Breaking changes: Use latest Hayt (2.x) https://github.com/mpenet/hayt/blob/master/CHANGELOG.md
- Use latest Hayt https://github.com/mpenet/hayt/blob/master/CHANGELOG.md
- Fix/modify ExceptionInfo map, we don't try to get queryString manually since it's not always available (BoundStatement vs Statement) and generates an error.
-
Improved exception handling, query execution/binding/preparation exception are now ExceptionInfo instances that hold a map with the original statement and the Query string used. You can get to this info from the ExceptionInfo instance using
clojure.core/ex-data
.(try (execute "slect prout from 1;") (catch Exception ex (println (ex-data ex))))
The map looks like this:
{:exception #<SyntaxError com.datastax.driver.core.exceptions.SyntaxError: line 1:0 no viable alternative at input 'slect'> :query "slect prout from 1;" :values nil :statement #<SimpleStatement slect prout from 1;>}
- Use java-driver 1.0.4 driver-core/CHANGELOG
- Add add support for
:socket-options
and:defer-initialization
viacluster
options - Use new java-driver 1.0.4 api for pooling-options & socket-options (backward compatible)
- Update clojure.core.async dependency and cleanup project.clj
prepare
used to be able to convert the query argument when coming from hayt using->prepared
and only take the first value of the returned vector. While this was useful, this was often hiding the resulting query and limiting in some way (you don't necessarly want to have every value prepared), forcing the user to compile it in the repl first to have an idea of what it would look like.prepare
has been changed so that it never compiles with->prepare
but now does it with->raw
. Meaning you can now do the following(prepare (select :foo (where {:bar ?})))
You can still useprepare
with queries generated with->prepared
you just need to do it explicitly
(def pq (->prepared (select :foo (where {:bar 1}))))
(prepare (first pq))
...
- Use latest Hayt https://github.com/mpenet/hayt/blob/master/CHANGELOG.md
- Allow to pass keyspace id as a keyword in
qbits.alia/connect
- Use latest Hayt https://github.com/mpenet/hayt/blob/master/CHANGELOG.md
- Use latest Hayt https://github.com/mpenet/hayt/blob/master/CHANGELOG.md
- Use clojure.core.async alpha release instead of SNAPSHOT
- Use java-driver 1.0.3 driver-core/CHANGELOG
-
Use latest Hayt https://github.com/mpenet/hayt/blob/master/CHANGELOG.md
-
Make sure namespace keywords are properly encoded in prepared statements
- Add support for clojure.core.async via
qbits.alia/execute-chan
, returning a channel usable with go blocks orclojure.core.async/take!
.
- Use latest Hayt https://github.com/mpenet/hayt/blob/master/CHANGELOG.md
- Use java-driver 1.0.2 driver-core/CHANGELOG
-
Use java-driver 1.0.1 driver-core/CHANGELOG
-
Add SSL support
- Update core.memoize dependency (fixes annoying assert bug)
- Make it clj 1.4+ compatible instead of 1.5+ (dependency on latest hayt)
- Add support for raw byte-arrays from hayt queries and prepared statements
- Add support for hayt query input in
alia/prepare
-
bump hayt to 1.0.5 https://github.com/mpenet/hayt/blob/master/CHANGELOG.md#105
-
bump core.memoize to 0.5.5
- add simple wrapper to time 1 UUIDs
- update dependency
core.memoize
to 0.5.4
- ResultSet decoding performance improvements
- Added support for
JMXReporting
toggling at the cluster level
-
qbits.tardis
is now optional -
Added wrappers for retry/load-balancing/reconnection policies see
qbits.alia.policy.*
-
Added
qbits.alia/lazy-query
: lazy sequences over CQL queries -
Depend on hayt 1.0.2 (bugfixes)
:auth-info
option oncluster
becomes:credentials
as SimpleAuthInfoProvider is gone and replaced with .withCredentials.
-
Upgraded to java-driver rc1
-
Upgraded hayt to 0.5.0
-
Restored
keywordize?
- Lift restriction on nil values (supported in C* 1.2.4+)
- remove
keywordize
option, useless feature
-
Update java-driver to beta2, see driver-core/CHANGELOG
-
Metadata on results updated to follow java-driver's style, it now returns an
:execution-info
key that contains basic info about the query (hosts queried etc) and allows to retrieve tracing info, in future versions paging metadata probably, see JAVA-65. -
C* CUSTOM type support see JAVA-61
-
async-execute
now returns alamina.core/result-channel
, the only difference for end-users should be the behavior when an error occurs and the query is dereferenced: it used to return the exception as a value, now it throws it, callbacks are unchanged. -
Added Lamina as a dependency.
-
BREAKING CHANGE: Column names are now returned as keywords by default (way more convenient in real world use), you can change that globally using
set-keywordize!
or per query using the:keywordize?
option onexecute
/execute-async
calls. -
Depend on clojure 1.5.1 by default.
- update hayt to 0.4.0-beta3
- update core.memoize to 0.5.3
- minor code changes to avoid repetitions in alia.clj
- add hayt raw query execution support, with query caching.
- update hayt to 0.4.0-beta1
- add
keywordize?
options toexecute
andexecute-async
, make it settable globally withset-keywordize!
.
- Breaking change!
Add
execute-async
: use distinct functions for sync/async mode since they don't share return types and some optional parameters. This meansexecute
no longer accepts the:async?
option, useexecute-async
instead.
-
fixed pooling options only allowing one distance setting, and also make it use hash-map as value
:core-connections-per-host {:remote 10 :local 100}