GithubHelp home page GithubHelp logo

codax's Issues

Add examples of nippy

Hi @dscarpetti

First off, thanks for this wonderful library!

My request is that could you please add some nippy exames in the ReadMe ? I'm a beginner in clojure so I'd love to see a couple examples of non-map data being stored via nippy.

Return only keys?

I have multiple projects for which I only want to know their ID (keys).

Usually I would simply do this (or the Codax equivalent):

(keys projects-db)

Once I have the keys I could use c/get-at to only fetch the information I want.

However this is taking way too much time, most probably because Codax is loading the entire map even when I only need the keys.
Is there an alternative approach to obtain the same info without loading everything?

let did not conform to spec

after upgraded to [codax "1.0.1-SNAPSHOT"]

clojure.lang.Compiler$CompilerException: clojure.lang.ExceptionInfo: Call to clojure.core/let did not conform to spec:
In: [0 0] val: (if (get no-graphs (first path)) (get-in)) fails spec: :clojure.core.specs.alpha/local-name at: [:args :bindings :binding :sym] predicate: simple-symbol?
In: [0 0] val: (if (get no-graphs (first path)) (get-in)) fails spec: :clojure.core.specs.alpha/seq-binding-form at: [:args :bindings :binding :seq] predicate: vector?
In: [0 0 0] val: if fails spec: :clojure.core.specs.alpha/map-binding at: [:args :bindings :binding :map :mb] predicate: vector?
In: [0 0 0] val: if fails spec: :clojure.core.specs.alpha/ns-keys at: [:args :bindings :binding :map :nsk] predicate: vector?
In: [0 0 0] val: if fails spec: :clojure.core.specs.alpha/map-bindings at: [:args :bindings :binding :map :msb] predicate: vector?
In: [0 0 1] val: (get no-graphs (first path)) fails spec: :clojure.core.specs.alpha/map-binding at: [:args :bindings :binding :map :mb] predicate: vector?
In: [0 0 1] val: (get no-graphs (first path)) fails spec: :clojure.core.specs.alpha/ns-keys at: [:args :bindings :binding :map :nsk] predicate: vector?
In: [0 0 1] val: (get no-graphs (first path)) fails spec: :clojure.core.specs.alpha/map-bindings at: [:args :bindings :binding :map :msb] predicate: vector?
In: [0 0 2] val: (get-in) fails spec: :clojure.core.specs.alpha/map-binding at: [:args :bindings :binding :map :mb] predicate: vector?
In: [0 0 2] val: (get-in) fails spec: :clojure.core.specs.alpha/ns-keys at: [:args :bindings :binding :map :nsk] predicate: vector?
In: [0 0 2] val: (get-in) fails spec: :clojure.core.specs.alpha/map-bindings at: [:args :bindings :binding :map :msb] predicate: vector?
In: [0 0] val: (if (get no-graphs (first path)) (get-in)) fails spec: :clojure.core.specs.alpha/map-special-binding at: [:args :bindings :binding :map] predicate: map?
:clojure.spec.alpha/args ([(if (get no-graphs (first path)) (get-in))])
{:clojure.spec.alpha/problems ({:path [:args :bindings :binding :sym], :pred simple-symbol?, :val (if (get no-graphs (first path)) (get-in)), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/local-name], :in [0 0]} {:path [:args :bindings :binding :seq], :pred vector?, :val (if (get no-graphs (first path)) (get-in)), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/seq-binding-form], :in [0 0]} {:path [:args :bindings :binding :map :mb], :pred vector?, :val if, :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/map-binding-form :clojure.core.specs.alpha/map-bindings :clojure.core.specs.alpha/map-binding], :in [0 0 0]} {:path [:args :bindings :binding :map :nsk], :pred vector?, :val if, :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/map-binding-form :clojure.core.specs.alpha/map-bindings :clojure.core.specs.alpha/ns-keys], :in [0 0 0]} {:path [:args :bindings :binding :map :msb], :pred vector?, :val if, :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/map-binding-form :clojure.core.specs.alpha/map-bindings], :in [0 0 0]} {:path [:args :bindings :binding :map :mb], :pred vector?, :val (get no-graphs (first path)), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/map-binding-form :clojure.core.specs.alpha/map-bindings :clojure.core.specs.alpha/map-binding], :in [0 0 1]} {:path [:args :bindings :binding :map :nsk], :pred vector?, :val (get no-graphs (first path)), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/map-binding-form :clojure.core.specs.alpha/map-bindings :clojure.core.specs.alpha/ns-keys], :in [0 0 1]} {:path [:args :bindings :binding :map :msb], :pred vector?, :val (get no-graphs (first path)), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/map-binding-form :clojure.core.specs.alpha/map-bindings], :in [0 0 1]} {:path [:args :bindings :binding :map :mb], :pred vector?, :val (get-in), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/map-binding-form :clojure.core.specs.alpha/map-bindings :clojure.core.specs.alpha/map-binding], :in [0 0 2]} {:path [:args :bindings :binding :map :nsk], :pred vector?, :val (get-in), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/map-binding-form :clojure.core.specs.alpha/map-bindings :clojure.core.specs.alpha/ns-keys], :in [0 0 2]} {:path [:args :bindings :binding :map :msb], :pred vector?, :val (get-in), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/map-binding-form :clojure.core.specs.alpha/map-bindings], :in [0 0 2]} {:path [:args :bindings :binding :map], :pred map?, :val (if (get no-graphs (first path)) (get-in)), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/binding :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/binding-form :clojure.core.specs.alpha/map-binding-form :clojure.core.specs.alpha/map-special-binding], :in [0 0]}), :clojure.spec.alpha/args ([(if (get no-graphs (first path)) (get-in))])}, compiling:(viri/db.clj:157:18)

AOT causes problem with clojurescript

When using 1.2.0-snapshot and running figwheel, I get this error :

  No reader function for tag Inf

  986  (js-mod (Math/floor o) 2147483647)
  987  (case o
  988    ##Inf
              ^--- No reader function for tag Inf
  989    2146435072
  990    ##-Inf
  991    -1048576

However, re-adding ^:skip-aot solve this.

Issue in with-write-transaction

I'm doing like this:

(defn init-db [ db ]
(c/with-write-transaction [db tx]
(when-not (c/get-at tx [:counters :user-id])
(c/assoc-at tx [:counters :user-id] 1))))

This is for the one-time DB initialization. As you see, if the DB was already initialized, the body of the when-not will not be evaluated, nothing is written to DB. This leads to NullPointerException clojure.lang.RT.longCast (RT.java:1259)

Error after :require codax

Any idea how to fix this? I really want to use it. ๐Ÿ˜ฐ
clojure.lang.Compiler$CompilerException: clojure.lang.ExceptionInfo: Call to clojure.core/defn did not conform to spec: In: [0] val: codax.pathwise/encode-element fails spec: :clojure.core.specs.alpha/defn-args at: [:args :name] predicate: simple-symbol? :clojure.spec.alpha/args (codax.pathwise/encode-element [el65854] (clojure.core/cond (true? el65854) (clojure.core/str (clojure.core/char 33) ((fn [_] "") el65854) codax.pathwise/+delim+) (date-time? el65854) (clojure.core/str (clojure.core/char 36) (encode-date-time el65854) codax.pathwise/+delim+) (neg-infinity? el65854) (clojure.core/str (clojure.core/char 48) ((fn [_] "") el65854) codax.pathwise/+delim+) (pos-infinity? el65854) (clojure.core/str (clojure.core/char 50) ((fn [_] "") el65854) codax.pathwise/+delim+) (number? el65854) (clojure.core/str (clojure.core/char 49) (encode-number el65854) codax.pathwise/+delim+) (symbol? el65854) (clojure.core/str (clojure.core/char 104) (encode-symbol el65854) codax.pathwise/+delim+) (false? el65854) (clojure.core/str (clojure.core/char 32) ((fn [_] "") el65854) codax.pathwise/+delim+) (string? el65854) (clojure.core/str (clojure.core/char 112) (encode-string el65854) codax.pathwise/+delim+) ((fn* [p1__65853#] (or (vector? p1__65853#) (list? p1__65853#))) el65854) (clojure.core/str (clojure.core/char 160) (encode-vector el65854) codax.pathwise/+delim+) (keyword? el65854) (clojure.core/str (clojure.core/char 105) (encode-keyword el65854) codax.pathwise/+delim+) (nil? el65854) (clojure.core/str (clojure.core/char 16) ((fn [_] "") el65854) codax.pathwise/+delim+) :else (throw (java.lang.Exception. (clojure.core/str "no method for encoding " el65854 ""))))) {:clojure.spec.alpha/problems [{:path [:args :name], :pred simple-symbol?, :val codax.pathwise/encode-element, :via [:clojure.core.specs.alpha/defn-args :clojure.core.specs.alpha/defn-args], :in [0]}], :clojure.spec.alpha/args (codax.pathwise/encode-element [el65854] (clojure.core/cond (true? el65854) (clojure.core/str (clojure.core/char 33) ((fn [_] "") el65854) codax.pathwise/+delim+) (date-time? el65854) (clojure.core/str (clojure.core/char 36) (encode-date-time el65854) codax.pathwise/+delim+) (neg-infinity? el65854) (clojure.core/str (clojure.core/char 48) ((fn [_] "") el65854) codax.pathwise/+delim+) (pos-infinity? el65854) (clojure.core/str (clojure.core/char 50) ((fn [_] "") el65854) codax.pathwise/+delim+) (number? el65854) (clojure.core/str (clojure.core/char 49) (encode-number el65854) codax.pathwise/+delim+) (symbol? el65854) (clojure.core/str (clojure.core/char 104) (encode-symbol el65854) codax.pathwise/+delim+) (false? el65854) (clojure.core/str (clojure.core/char 32) ((fn [_] "") el65854) codax.pathwise/+delim+) (string? el65854) (clojure.core/str (clojure.core/char 112) (encode-string el65854) codax.pathwise/+delim+) ((fn* [p1__65853#] (or (vector? p1__65853#) (list? p1__65853#))) el65854) (clojure.core/str (clojure.core/char 160) (encode-vector el65854) codax.pathwise/+delim+) (keyword? el65854) (clojure.core/str (clojure.core/char 105) (encode-keyword el65854) codax.pathwise/+delim+) (nil? el65854) (clojure.core/str (clojure.core/char 16) ((fn [_] "") el65854) codax.pathwise/+delim+) :else (throw (java.lang.Exception. (clojure.core/str "no method for encoding " el65854 "")))))}, compiling:(codax/pathwise.clj:108:1)

Support for java.time Instants

The author of joda time has contributed java.time, and considers it an improved effort. Modern clojure libs are also preferring java.time.

What are the steps we can take to add support for this type as keys in the db map?

Gracefully upgrade from a read to write transaction

Would it be possible to offer a way to upgrade a read transaction to a write transaction without starting the transaction from scratch?

It would be very helpful when chaining functions where a write might occur. Especially given the superior speed of read transactions.

Error while 2 sequential writes in 1 transaction

I have following function

(defn create-user! [ email password db]
  (c/with-write-transaction [db tx]
    (let [encrypted-password (p/encrypt password)
          next-user-id (inc (c/get-at tx [:counters :user-id]))
          user {:email email
                :password-hash encrypted-password}]
      (c/merge-at tx [:users] {next-user-id user})
      (c/assoc-at tx [:counters :user-id] next-user-id))))

As you see I have one read and two writes within one transaction. But only the last write occurs. I expect that both writes should occur.

Error requiring codax

I created an app with lein new luminus myapp, added codax to project.clj and required it in src/clj/myapp/routes/home.clj.

After running lein run I get the following error:
Exception in thread "main" java.lang.ExceptionInInitializerError at clojure.main.<clinit>(main.java:20) Caused by: java.lang.IllegalArgumentException: No matching method: repl, compiling:(codax/core.clj:161:3) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6875) at clojure.lang.Compiler.analyze(Compiler.java:6669) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6856) at clojure.lang.Compiler.analyze(Compiler.java:6669) at clojure.lang.Compiler.analyze(Compiler.java:6625) at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:6001) at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5380) at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3972) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6866) at clojure.lang.Compiler.analyze(Compiler.java:6669) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6856) at clojure.lang.Compiler.analyze(Compiler.java:6669) at clojure.lang.Compiler.access$300(Compiler.java:38) at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:589) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6868) at clojure.lang.Compiler.analyze(Compiler.java:6669) at clojure.lang.Compiler.analyze(Compiler.java:6625) at clojure.lang.Compiler.eval(Compiler.java:6931) at clojure.lang.Compiler.load(Compiler.java:7379) at clojure.lang.RT.loadResourceScript(RT.java:372) at clojure.lang.RT.loadResourceScript(RT.java:363) at clojure.lang.RT.load(RT.java:453) at clojure.lang.RT.load(RT.java:419) at clojure.core$load$fn__5677.invoke(core.clj:5893) at clojure.core$load.invokeStatic(core.clj:5892) at clojure.core$load.doInvoke(core.clj:5876) at clojure.lang.RestFn.invoke(RestFn.java:408) at clojure.core$load_one.invokeStatic(core.clj:5697) at clojure.core$load_one.invoke(core.clj:5692) at clojure.core$load_lib$fn__5626.invoke(core.clj:5737) at clojure.core$load_lib.invokeStatic(core.clj:5736) at clojure.core$load_lib.doInvoke(core.clj:5717) at clojure.lang.RestFn.applyTo(RestFn.java:142) at clojure.core$apply.invokeStatic(core.clj:648) at clojure.core$load_libs.invokeStatic(core.clj:5774) at clojure.core$load_libs.doInvoke(core.clj:5758) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply.invokeStatic(core.clj:648) at clojure.core$require.invokeStatic(core.clj:5796) at clojure.core$require.doInvoke(core.clj:5796) at clojure.lang.RestFn.invoke(RestFn.java:482) at myapp.routes.home$eval5414$loading__5569__auto____5415.invoke(home.clj:1) at myapp.routes.home$eval5414.invokeStatic(home.clj:1) at myapp.routes.home$eval5414.invoke(home.clj:1) at clojure.lang.Compiler.eval(Compiler.java:6927) at clojure.lang.Compiler.eval(Compiler.java:6916) at clojure.lang.Compiler.load(Compiler.java:7379) at clojure.lang.RT.loadResourceScript(RT.java:372) at clojure.lang.RT.loadResourceScript(RT.java:363) at clojure.lang.RT.load(RT.java:453) at clojure.lang.RT.load(RT.java:419) at clojure.core$load$fn__5677.invoke(core.clj:5893) at clojure.core$load.invokeStatic(core.clj:5892) at clojure.core$load.doInvoke(core.clj:5876) at clojure.lang.RestFn.invoke(RestFn.java:408) at clojure.core$load_one.invokeStatic(core.clj:5697) at clojure.core$load_one.invoke(core.clj:5692) at clojure.core$load_lib$fn__5626.invoke(core.clj:5737) at clojure.core$load_lib.invokeStatic(core.clj:5736) at clojure.core$load_lib.doInvoke(core.clj:5717) at clojure.lang.RestFn.applyTo(RestFn.java:142) at clojure.core$apply.invokeStatic(core.clj:648) at clojure.core$load_libs.invokeStatic(core.clj:5774) at clojure.core$load_libs.doInvoke(core.clj:5758) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply.invokeStatic(core.clj:648) at clojure.core$require.invokeStatic(core.clj:5796) at clojure.core$require.doInvoke(core.clj:5796) at clojure.lang.RestFn.invoke(RestFn.java:551) at myapp.handler$eval288$loading__5569__auto____289.invoke(handler.clj:1) at myapp.handler$eval288.invokeStatic(handler.clj:1) at myapp.handler$eval288.invoke(handler.clj:1) at clojure.lang.Compiler.eval(Compiler.java:6927) at clojure.lang.Compiler.eval(Compiler.java:6916) at clojure.lang.Compiler.load(Compiler.java:7379) at clojure.lang.RT.loadResourceScript(RT.java:372) at clojure.lang.RT.loadResourceScript(RT.java:363) at clojure.lang.RT.load(RT.java:453) at clojure.lang.RT.load(RT.java:419) at clojure.core$load$fn__5677.invoke(core.clj:5893) at clojure.core$load.invokeStatic(core.clj:5892) at clojure.core$load.doInvoke(core.clj:5876) at clojure.lang.RestFn.invoke(RestFn.java:408) at clojure.core$load_one.invokeStatic(core.clj:5697) at clojure.core$load_one.invoke(core.clj:5692) at clojure.core$load_lib$fn__5626.invoke(core.clj:5737) at clojure.core$load_lib.invokeStatic(core.clj:5736) at clojure.core$load_lib.doInvoke(core.clj:5717) at clojure.lang.RestFn.applyTo(RestFn.java:142) at clojure.core$apply.invokeStatic(core.clj:648) at clojure.core$load_libs.invokeStatic(core.clj:5774) at clojure.core$load_libs.doInvoke(core.clj:5758) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply.invokeStatic(core.clj:648) at clojure.core$require.invokeStatic(core.clj:5796) at clojure.core$require.doInvoke(core.clj:5796) at clojure.lang.RestFn.invoke(RestFn.java:551) at myapp.core$eval282$loading__5569__auto____283.invoke(core.clj:1) at myapp.core$eval282.invokeStatic(core.clj:1) at myapp.core$eval282.invoke(core.clj:1) at clojure.lang.Compiler.eval(Compiler.java:6927) at clojure.lang.Compiler.eval(Compiler.java:6916) at clojure.lang.Compiler.load(Compiler.java:7379) at clojure.lang.RT.loadResourceScript(RT.java:372) at clojure.lang.RT.loadResourceScript(RT.java:363) at clojure.lang.RT.load(RT.java:453) at clojure.lang.RT.load(RT.java:419) at clojure.core$load$fn__5677.invoke(core.clj:5893) at clojure.core$load.invokeStatic(core.clj:5892) at clojure.core$load.doInvoke(core.clj:5876) at clojure.lang.RestFn.invoke(RestFn.java:408) at clojure.core$load_one.invokeStatic(core.clj:5697) at clojure.core$load_one.invoke(core.clj:5692) at clojure.core$load_lib$fn__5626.invoke(core.clj:5737) at clojure.core$load_lib.invokeStatic(core.clj:5736) at clojure.core$load_lib.doInvoke(core.clj:5717) at clojure.lang.RestFn.applyTo(RestFn.java:142) at clojure.core$apply.invokeStatic(core.clj:648) at clojure.core$load_libs.invokeStatic(core.clj:5774) at clojure.core$load_libs.doInvoke(core.clj:5758) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply.invokeStatic(core.clj:648) at clojure.core$require.invokeStatic(core.clj:5796) at clojure.core$require.doInvoke(core.clj:5796) at clojure.lang.RestFn.invoke(RestFn.java:421) at user$eval3$loading__5569__auto____4.invoke(user.clj:1) at user$eval3.invokeStatic(user.clj:1) at user$eval3.invoke(user.clj:1) at clojure.lang.Compiler.eval(Compiler.java:6927) at clojure.lang.Compiler.eval(Compiler.java:6916) at clojure.lang.Compiler.load(Compiler.java:7379) at clojure.lang.RT.loadResourceScript(RT.java:372) at clojure.lang.RT.loadResourceScript(RT.java:359) at clojure.lang.RT.maybeLoadResourceScript(RT.java:355) at clojure.lang.RT.doInit(RT.java:475) at clojure.lang.RT.<clinit>(RT.java:331) ... 1 more Caused by: java.lang.IllegalArgumentException: No matching method: repl at clojure.lang.Compiler$StaticMethodExpr.<init>(Compiler.java:1642) at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java:1011) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6868) ... 136 more

I can comment out the require in home.clj and the project runs fine, uncomment it and everything still works. Any idea why this happens?

Non-breaking space in a map's keyword string

I'm a big fan of this library, many thanks!

I just stumbled over the following small issue: a "non-breaking space" in a string-key of a map produces

Execution error (NullPointerException) at codax.pathwise/eval9604$fn$fn$fn$fn (pathwise.clj:136).
Cannot invoke "Object.toString()" because "s" is null

Add support for maps as keys (pathwise)

Clojurians are used to be able to use pretty much anything as keys, including maps.

Codax is almost there, but lacks support for maps.

I came up with a simple encoder/decoder that leverages Nippy:

(ns my-ns
  (:require [codax.core :as c]
            [taoensso.nippy :as nippy])
  (:import (java.util Base64)))

;; Simply encoding bytes to strings (String. bytes) causes the data to
;; be corrupted after a round trip in Codax.  Encoding in b64 solves
;; this.

(defn bytes-to-base64 [bytes]
  (let [encoder (Base64/getEncoder)]
    (.encodeToString encoder bytes)))

(defn base64-to-bytes [base64-string]
  (let [decoder (Base64/getDecoder)]
    (.decode decoder base64-string)))

(c/defpathtype [0x71
                clojure.lang.PersistentHashMap
                clojure.lang.PersistentArrayMap
                clojure.lang.PersistentTreeMap]
  (fn map-encoder [m]
    (bytes-to-base64 (nippy/freeze m)))

  (fn map-decoder [s]
    (nippy/thaw (base64-to-bytes s))))

Nippy also automatically handles keys ordering:

(let [encoding1 (:encoding (c/check-path-encoding {{:a 1, :b 2} "map1"}))
      encoding2 (:encoding (c/check-path-encoding {{:b 2, :a 1} "map1"}))]
  (= encoding1 encoding2))

;=> true

Could something like this be added to Codax?
Could it leverage other types defined for pathwise?

Increasing file size

I've noticed that the codax file is increasing in size even when the stored map is small.
It seems related to the number of manipulations.

A small map (~100kb when in a text file) will give a nodes file bigger than 10Mb after a few dozens of overwrites.

with-write-transaction

I'm doing like this:

(defn init-db [ db ]
(c/with-write-transaction [db tx]
(when-not (c/get-at tx [:counters :user-id])
(c/assoc-at tx [:counters :user-id] 1))))

This is for the one-time DB initialization. As you see, if the DB was already initialized, the body of the when-not will not be evaluated, nothing is written to DB. This leads to NullPointerException clojure.lang.RT.longCast (RT.java:1259)

Function "open-database" is difficult to use within REPL

I have following code:

(defn init-db [ _db_ ]
  (c/assoc-at! _db_ [:counters :user-id] 1))

(def DB (atom nil))

(defn prepare-all [tests]
  (if-not @DB
    (reset! DB (c/open-database "db.test")))
  (init-db @DB))

(use-fixtures :once prepare-all)

As you see this code prepares database connection for tests. In my normal workflow I recompile this class multiple times and try running tests each time. All goes well but after recompiling the variable DB is redefined and opened connection is lost somewhere.

Your function has all of them stored:

(defn open-database [path & [backup-fn]]
  (let [path (to-canonical-path-string path)]
    (when (@open-databases path)
      (throw (ex-info "Database Already Open" {:cause :database-open
                                               :message "The database at this path is already open."
                                               :path path})))

So while I've lost the connection in my REPL it still physically exists somewhere and I cannot re-open the database again. I don't know how to fix this, maybe you can provide a function like "current-connection" accepting the database name so that I can obtain the existing connection and continue working without re-opening the DB?
Thanks!

Failing tests - Timezone related?

The tests relying on parsing dates (Ex: "June 6, 2020 11:01") fail because of a 2 hours difference between the expected and actual values.

  • codax.example-test/messaging-example
  • codax.example-test/bulk

I suspect this is because the parsed time is assumed to be in the local timezone, but the expected value is in UTC.

A possible alternative would be to leverage the #inst tag.
Seconds, milliseconds and the timezone can be omitted to reduce the visual noise:

#inst "2023-08-12T01:00"
; => #inst "2023-08-12T01:00:00.000-00:00"

The conversion to Instant is also pretty straightforward:

(.toInstant #inst "2023-08-12T01:00")
;=> #object[java.time.Instant 0x60208ef "2023-08-12T01:00:00Z"]

Before:

(simulate-message! "June 6, 2020 11:01" "Bobby" "Hello")

After:

(simulate-message! #inst "2020-06-06T11:01" "Bobby" "Hello")

Extend support for java.time

As discussed in #4 and #7 the java.time support should be extended from only Instants to include OffsetDateTimes and ZonedDateTimes as well. Ideally all with the same hex tag so that they sort together.

Remove clj-time (and Joda-Time) dependency

Joda-Time was nice a few years back, but nowadays Clojure users are expected to use java.util.Date (mostly via #inst) and java.time.instant.

Most importantly, clj-time is deprecated. It's a little annoying to bring those dependencies in new projects.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.