{"id":13408998,"url":"https://github.com/tirkarthi/clj-foundationdb","last_synced_at":"2025-09-11T19:31:36.730Z","repository":{"id":62435196,"uuid":"130835045","full_name":"tirkarthi/clj-foundationdb","owner":"tirkarthi","description":"A Clojure wrapper for FoundationDB","archived":false,"fork":false,"pushed_at":"2019-04-12T12:05:20.000Z","size":385,"stargazers_count":20,"open_issues_count":3,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-21T12:42:13.120Z","etag":null,"topics":["clojure","foundationdb"],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tirkarthi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-24T10:10:08.000Z","updated_at":"2025-01-01T16:30:51.000Z","dependencies_parsed_at":"2022-11-01T21:02:29.173Z","dependency_job_id":null,"html_url":"https://github.com/tirkarthi/clj-foundationdb","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/tirkarthi/clj-foundationdb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tirkarthi%2Fclj-foundationdb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tirkarthi%2Fclj-foundationdb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tirkarthi%2Fclj-foundationdb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tirkarthi%2Fclj-foundationdb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tirkarthi","download_url":"https://codeload.github.com/tirkarthi/clj-foundationdb/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tirkarthi%2Fclj-foundationdb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274694363,"owners_count":25332672,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-11T02:00:13.660Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","foundationdb"],"created_at":"2024-07-30T20:00:57.195Z","updated_at":"2025-09-11T19:31:36.431Z","avatar_url":"https://github.com/tirkarthi.png","language":"Clojure","funding_links":[],"categories":["Bindings"],"sub_categories":[],"readme":"# clj-foundationdb [![Build Status](https://travis-ci.org/tirkarthi/clj-foundationdb.svg?branch=master)](https://travis-ci.org/tirkarthi/clj-foundationdb) [![Clojars Project](https://img.shields.io/clojars/v/xtreak/clj-foundationdb.svg)](https://clojars.org/xtreak/clj-foundationdb) [![cljdoc](https://cljdoc.xyz/badge/xtreak/clj-foundationdb)](https://cljdoc.xyz/d/xtreak/clj-foundationdb)\n\nA Clojure wrapper for FoundationDB\n\n## Documentation\n\ncljdoc version : https://cljdoc.xyz/d/xtreak/clj-foundationdb/\n\ncodox version : https://tirkarthi.github.io/clj-foundationdb\n\n\nI am also trying to port a class scheduling app to Clojure using the library. Currently the API is still in a lot of fluctuation and hence the examples might not work but you can view the source at examples folder.\n\nReference implementation in Java : https://apple.github.io/foundationdb/class-scheduling-java.html\n\n## Examples\n\n```clojure\n\n(ns examples.main\n  (:require [clj-foundationdb.core :refer :all]\n            [clj-foundationdb.utils :refer :all]))\n\n;; Set a key\n\n(let [fd    (select-api-version 520)\n      key   \"foo\"\n      value 1]\n  (with-open [db (open fd)]\n    (tr! db\n         (set-val tr key value))))\n\nnil\n\n;; Get a key\n\n(let [fd    (select-api-version 520)\n      key   \"foo\"]\n  (with-open [db (open fd)]\n    (tr! db\n         (get-val tr key))))\n\n1\n\n;; Perform multiple operations in a single transaction\n\n(let [fd    (select-api-version 520)\n      key   \"foo\"\n      value 1]\n  (with-open [db (open fd)]\n    (tr! db\n         (set-val tr key value)\n         (get-val tr key))))\n\n1\n\n;; Set multiple keys with same value\n\n(let [fd    (select-api-version 520)\n      key   [[\"bar\"] [\"car\"] [\"dar\"] [\"far\"]]\n      value 1]\n  (with-open [db (open fd)]\n    (tr! db\n         (set-keys tr key value))))\n\nnil\n\n;; Get a range of keys\n\n(let [fd    (select-api-version 520)\n      begin \"car\"\n      end   \"far\"]\n  (with-open [db (open fd)]\n    (tr! db\n         (get-range tr begin end))))\n\n[[[\"car\"] 1] [[\"dar\"] 1]]\n\n;; Get all keys\n\n(let [fd    (select-api-version 520)]\n  (with-open [db (open fd)]\n    (tr! db\n         (get-all tr))))\n\n[[[\"bar\"] 1] [[\"car\"] 1] [[\"dar\"] 1] [[\"far\"] 1] [[\"foo\"] 1]]\n\n;; First key less than given key\n\n(let [fd    (select-api-version 520)\n      key   \"car\"]\n  (with-open [db (open fd)]\n    (tr! db\n         (last-less-than tr key))))\n\n[[[\"bar\"] 1]]\n\n;; First key greater than given key\n\n(let [fd    (select-api-version 520)\n      key   \"car\"]\n  (with-open [db (open fd)]\n    (tr! db\n         (first-greater-than tr key))))\n\n[[[\"dar\"] 1]]\n\n;; Nested keys\n\n(let [fd      (select-api-version 520)\n      classes [[\"class\" \"intro\"] [\"class\" \"algebra\"] [\"class\" \"maths\"] [\"class\" \"bio\"]]\n      time    \"10:00\"]\n  (with-open [db (open fd)]\n    (tr! db\n         (set-keys tr classes time)\n         (get-val tr [\"class\" \"algebra\"]))))\n\n\"10:00\"\n\n;; Automatic subspace prefix within a context\n\n(let [fd      (select-api-version 520)\n      classes [\"intro\" \"algebra\" \"maths\" \"bio\"]\n      time    \"10:00\"]\n  (with-open [db (open fd)]\n    (tr! db\n         (with-subspace \"class\"\n           (mapv #(set-val tr %1 time) classes)\n           (get-val tr \"algebra\")))))\n\n\"10:00\"\n```\n\n## Transaction basic example\n\nA basic example of the transactional nature of FoundationDB can be explained as below :\n\n* Set a key \"foo\" with value \"1\" and inside the transaction the value is set as \"1\"\n* Try changing the value to \"2\". You can see that inside the transaction the value of \"foo\" is \"2\" once it's changed. But when there is an exception the value is rolled back to \"1\"\n* Get the value of \"foo\" and it should return \"1\" since the previous transaction aborted with an exception and hence the value is not updated\n\n```clojure\nclj-foundationdb.core\u003e (let [fd    (select-api-version 520)\n                             key   \"foo\"\n                             value \"1\"]\n                         (with-open [db (open fd)]\n                           (tr! db\n                                (set-val tr key value)\n                                (get-val tr key))))\n\n1\n\nclj-foundationdb.core\u003e (let [fd    (select-api-version 520)\n                             key   \"foo\"\n                             value \"2\"]\n                         (with-open [db (open fd)]\n                           (tr! db\n                                (println (get-val tr key))\n                                (set-val tr key value)\n                                (println (get-val tr key))\n                                (/ 1 0))))\n\n1\n2\nArithmeticException Divide by zero  clojure.lang.Numbers.divide (Numbers.java:163)\n\nclj-foundationdb.core\u003e (let [fd    (select-api-version 520)\n                             key   \"foo\"\n                             value \"1\"]\n                         (with-open [db (open fd)]\n                           (tr! db\n                                (get-val tr key))))\n1\n```\n\n## Tuple encoding and alternatives\n\nThis library uses tuple encoding so that manual encoding and decoding is not necessary. If you want a more thin wrapper please use [clj_fdb](https://github.com/vedang/clj_fdb/). Relevant issue : https://github.com/tirkarthi/clj-foundationdb/issues/15\n\n## Stability\n\nThe API is still in early development stages and is subjected to change. It's building up nicely and comments are welcome.\n\n### JDK 7 support\n\nThe underlying Java library uses lambdas and hence the minimum supported version is JDK 8.\n\n## Benchmarks\n\nBenchmarks are quite tricky to get right. The main factor with FoundationDB is that everything opens up a new transaction and hence making it slow. But bulk writes are faster.\n\n### System Info\n\n```\n➜  clj-foundationdb git:(master) ✗ system_profiler SPHardwareDataType\nHardware:\n\n    Hardware Overview:\n\n      Model Name: MacBook Air\n      Model Identifier: MacBookAir7,2\n      Processor Name: Intel Core i5\n      Processor Speed: 1.6 GHz\n      Number of Processors: 1\n      Total Number of Cores: 2\n      L2 Cache (per Core): 256 KB\n      L3 Cache: 3 MB\n      Memory: 4 GB\n      Boot ROM Version: MBA71.0166.B06\n      SMC Version (system): 2.27f2\n      Serial Number (system): C02Q4LHTG940\n      Hardware UUID: 4ECF3B7B-6444-51AA-BB60-BCE6C285D90D\n```\n\n### FoundationDB single writes\n\n```\n(let [fd    (select-api-version 520)\n      key   \"foo\"\n      value \"1\"]\n      (with-open [db (open fd)]\n\t        (quick-bench (doall (for [_ (range 100)] (tr! db (set-val tr key value)))))))\nEvaluation count : 6 in 6 samples of 1 calls.\n             Execution time mean : 1.845528 sec\n    Execution time std-deviation : 58.156807 ms\n   Execution time lower quantile : 1.795201 sec ( 2.5%)\n   Execution time upper quantile : 1.934851 sec (97.5%)\n                   Overhead used : 2.028213 ns\n\nFound 1 outliers in 6 samples (16.6667 %)\n\tlow-severe\t 1 (16.6667 %)\n Variance from outliers : 13.8889 % Variance is moderately inflated by outliers\n```\n\n### FoundationDB batch writes\n\n\n```\n(defn set-val-n\n  \"Set a value for the key\"\n  [tr key value n]\n  (dotimes [_ n]\n     (.set tr key value)))\n\nclj-foundationdb.core\u003e (let [fd (select-api-version 520)\n                             key (.getBytes \"foo\")\n                             value (.getBytes \"10000\")]\n                         (with-open [db (open fd)]\n                           (quick-bench (tr! db (set-val-n tr key value 100000)))))\nEvaluation count : 6 in 6 samples of 1 calls.\n             Execution time mean : 625.745197 ms\n    Execution time std-deviation : 72.918243 ms\n   Execution time lower quantile : 542.717590 ms ( 2.5%)\n   Execution time upper quantile : 718.452721 ms (97.5%)\n                   Overhead used : 2.028213 ns\n\n```\n\n### FoundationDB write 1 million keys with 10 parallel clients and 100k keys per client\n\n1 million keys set in 23.74 seconds\n\n```clojure\n(let [fd (select-api-version 520)\n      kv (map #(vector (str %1) %1) (range 100000))]\n  (time (let [clients (repeatedly 10 #(future\n                                        (with-open [db (open fd)]\n                                          (tr! db\n                                               (doall (doseq [[k v] kv]\n                                                        (set-val tr k v)))))))]\n          (doall (map deref clients))\n          \"Finished\")))\n\"Elapsed time: 23740.242199 msecs\"\n\"Finished\"\n```\n\n### FoundationDB read 100k keys with 10 parallel clients and 10k keys per client\n\n100k keys read took 16.81 seconds\n\n```\n(let [fd (select-api-version 520)\n      kv (map #(vector (str %1) %1) (range 100000))]\n  (time (with-open [db (open fd)]\n          (let [clients (repeatedly 10 #(future\n                                          (tr! db\n                                               (doall (doseq [k (range 10000)]\n                                                        (get-val tr k))))))]\n            (doall (map deref clients)))\n          \"Finished\")))\n\"Elapsed time: 16818.560737 msecs\"\n\"Finished\"\n```\n\nYou can find some more numbers for FoundationDB [here](https://apple.github.io/foundationdb/benchmarking.html)\n\n### Redis\n\n```\n➜  redis git:(unstable) redis-benchmark -t set\n====== SET ======\n  100000 requests completed in 1.59 seconds\n  50 parallel clients\n  3 bytes payload\n  keep alive: 1\n\n96.52% \u003c= 1 milliseconds\n99.95% \u003c= 2 milliseconds\n99.97% \u003c= 6 milliseconds\n100.00% \u003c= 6 milliseconds\n62853.55 requests per second\n```\n\n### Redis with pipelining\n\n```\n➜  redis git:(unstable) redis-benchmark -t set -P 160\n====== SET ======\n  100000 requests completed in 0.17 seconds\n  50 parallel clients\n  3 bytes payload\n  keep alive: 1\n\n0.00% \u003c= 1 milliseconds\n0.64% \u003c= 2 milliseconds\n1.12% \u003c= 5 milliseconds\n2.72% \u003c= 6 milliseconds\n4.48% \u003c= 10 milliseconds\n8.48% \u003c= 11 milliseconds\n36.96% \u003c= 12 milliseconds\n65.12% \u003c= 13 milliseconds\n82.40% \u003c= 14 milliseconds\n95.36% \u003c= 15 milliseconds\n99.04% \u003c= 16 milliseconds\n100.00% \u003c= 16 milliseconds\n595238.12 requests per second\n```\n\n## License\n\nCopyright © 2018 Karthikeyan S\n\nDistributed under the MIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftirkarthi%2Fclj-foundationdb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftirkarthi%2Fclj-foundationdb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftirkarthi%2Fclj-foundationdb/lists"}