{"id":32181306,"url":"https://github.com/sixthnormal/clj-3df","last_synced_at":"2026-02-21T13:01:28.262Z","repository":{"id":62432106,"uuid":"136314918","full_name":"sixthnormal/clj-3df","owner":"sixthnormal","description":"Clojure(Script) client for Declarative Dataflow.","archived":false,"fork":false,"pushed_at":"2019-11-08T16:36:09.000Z","size":234,"stargazers_count":332,"open_issues_count":16,"forks_count":13,"subscribers_count":24,"default_branch":"master","last_synced_at":"2025-12-13T05:01:31.225Z","etag":null,"topics":["client","clojure","datalog","differential-dataflows","relational"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sixthnormal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-06T10:49:13.000Z","updated_at":"2025-10-31T09:05:06.000Z","dependencies_parsed_at":"2022-11-01T21:00:58.806Z","dependency_job_id":null,"html_url":"https://github.com/sixthnormal/clj-3df","commit_stats":null,"previous_names":["comnik/clj-3df"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sixthnormal/clj-3df","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sixthnormal%2Fclj-3df","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sixthnormal%2Fclj-3df/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sixthnormal%2Fclj-3df/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sixthnormal%2Fclj-3df/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sixthnormal","download_url":"https://codeload.github.com/sixthnormal/clj-3df/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sixthnormal%2Fclj-3df/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29681468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T12:30:22.644Z","status":"ssl_error","status_checked_at":"2026-02-21T12:29:55.402Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["client","clojure","datalog","differential-dataflows","relational"],"created_at":"2025-10-21T22:41:31.140Z","updated_at":"2026-02-21T13:01:28.248Z","avatar_url":"https://github.com/sixthnormal.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# clj-3df\n\n[![Clojars Project](https://img.shields.io/clojars/v/com.sixthnormal/clj-3df.svg)](https://clojars.org/com.sixthnormal/clj-3df)\n\n**This is alpha-quality software, not feature-complete, and not yet\nready for use in production services.**\n\n3DF is best thought of as a pub/sub system in which subscriptions can\nbe arbitrary Datalog expressions. Subscribers register queries with\nthe broker, and data sources (such as Kafka, Datomic, or any other\nsource-of-truth) publish new data to it. All subscriber queries\naffected by incoming data will be notified with a diff, describing how\ntheir results have changed. The Datalog implementation is modeled\nafter [Datomic's query\nlanguage](https://docs.datomic.com/on-prem/query.html) and aims to\nsupport the same set of features.\n\n3DF does this efficiently, thanks to being built on top of\n[differential\ndataflows](https://github.com/frankmcsherry/differential-dataflow). In\nparticular, Differential Dataflow will only compute changes, rather\nthan execute a computation from scratch.\n\nThis repository contains the Clojure client for 3DF. The broker is\nwritten in Rust and can be found in the [Declarative Differential\nDataflows](https://github.com/comnik/declarative-dataflow) repository.\n\n## How it works\n\nThe 3DF client compiles Datalog expressions into an intermediate\nrepresentation that can be synthesised into a differential dataflow on\nthe server. This dataflow is then registered and executed across any\nnumber of workers. Whenever query results change due to new data\nentering the system, the server will push the neccessary changes via a\nWebSocket connection.\n\nFor example, consider a subscriber created the following subscription:\n\n``` clojure\n(exec! conn\n  (query db \"user inbox\" \n    '[:find ?msg ?content\n      :where \n      [?msg :msg/recipient \"me@nikolasgoebel.com\"]\n      [?msg :msg/content ?content]]))\n```\n\nand a new message arrives in the system.\n\n``` clojure\n[{:msg/receipient \"me@nikolasgoebel.com\"\n  :msg/content    \"Hello!\"}]\n```\n\nThen the server will push the following results to the subscriber:\n\n``` clojure\n[[[\u003cmsg-id\u003e \"Hello!\"] +1]]\n```\n\nIf at some later point in time, this message was retracted\n\n``` clojure\n[[:db/retractEntity \u003cmsg-id\u003e]]\n```\n\nthe server would again notify the subscriber, this time indicating the\nretraction:\n\n``` clojure\n[[[\u003cmsg-id\u003e \"Hello!\"] -1]]\n```\n\nThis guarantees, that subscribers maintaining any form of functionally\nderived information will always have a consistent view of the data.\n\n## Query Language Features\n\n- [x] Implicit joins and unions, `and` / `or` operators\n- [x] Stratified negation\n- [x] Parameterized queries\n- [x] Rules, self-referential / mutually recursive rules\n- [x] Aggregation (min, max, count, etc...)\n- [x] Grouping via `:with`\n- [x] Basic predicates (\u003c=, \u003c, \u003e, \u003e=, =, not=)\n- [ ] As-of queries\n- [ ] More find specifications (e.g. collection, scalar)\n- [ ] Pull queries\n- [x] Queries across many heterogeneous data sources\n\nPlease also have a look at the open issues to get a sense for what\nwe're working on.\n\n## Non-Features\n\n3DF is neither concerned with durability nor with consistency in the\nACID sense. It is intended to be used in combination with a\nconsistent, durable source-of-truth such as\n[Datomic](https://www.datomic.com/) or\n[Kafka](https://kafka.apache.org/).\n\nConsequently, 3DF will accept whatever tuples it is supplied with. For\nexample, whereas in Datomic two subsequent transactions on an empty\ndatabase\n\n``` clojure\n(d/transact conn [[:db/add 123 :user/balance 1000]])\n...\n(d/transact conn [[:db/add 123 :user/balance 1500]])\n```\n\nwould result in the following sets of datoms being added into the\ndatabase:\n\n``` clojure\n[[123 :user/balance 1000 \u003ctx1\u003e true]]\n...\n[[123 :user/balance 1000 \u003ctx2\u003e false]\n [123 :user/balance 1500 \u003ctx2\u003e true]]\n```\n\n3DF will by itself not take any previous information into account on\ntransactions. Again, 3DF is intended to be fed data from a system like\nDatomic, which would ensure that transactions produce consistent\ntuples.\n\n## License\n\nCopyright © 2018 Nikolas Göbel\n\nLicensed under Eclipse Public License (see [LICENSE](LICENSE)).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsixthnormal%2Fclj-3df","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsixthnormal%2Fclj-3df","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsixthnormal%2Fclj-3df/lists"}