Datomic Pro and Datomic Cloud are FREE!

Excision

Motivation

It is a key value proposition of Datomic that you can tell not only what you know, but how you came to know it.  When you add a fact:

conn.transact(list(":db/add", 42, ":firstName", "John"));

Datomic does more than merely record that 42's first name is "John".  Each datom is also associated with a transaction entity, which records the moment (:db/txInstant) the datom was recorded.


Given these reified transactions, it is possible to track the history of information.  Let's say John decides he prefers to go by "Jack":

conn.transact(list(":db/add", 42, ":firstName", "Jack"));

When you assert a new value for a cardinality-one attribute such as :firstName, Datomic will automatically retract any past value (cardinality-one means that you cannot have two first names simultaneously).  So now the database looks like this:

Given this information model, it is easy to see that Datomic can support queries that tell you:
  • what you know now
  • what you knew at some point in the past
  • how and when you came to know any particular datom
So far so good, but there is a fly in the ointment.  In certain situations you may be forced to excise data, pulling it out root and branch and forgetting that you ever knew it.  This may happen if you store data that must comply with privacy or IP laws, or you may have a regulatory requirement to keep records for seven years and then "shred" them.  For these scenarios, Datomic provides excision.

Excision in Datomic

You can request excision of data by transacting a new entity with the following attributes:
  • :db/excise is required, and refers to a target entity or attribute to be excised. Thus there are two scenarios - excise all or part of an entity, or excise some or all of the values of a particular attribute.
  • :db.excise/attrs is an optional, cardinality-many, reference attribute that limits an excision to a set of attributes, useful only when the target of excise is an entity. (If :db.excise/attrs are not specified, then all matching attributes will be excised.)
  • :db.excise/beforeT is an optional, long-valued attribute that limits an excision to only datoms whose t is before the specified beforeT, which may be a t or tx id. This can be used with entity or attribute targets.
  • :db.excise/before is an optional, instant-valued attribute that limits an excision to only datoms whose transaction time is before the specified before. This can be used with entity or attribute targets.

Example: Excising Specific Entities

To excise a specific entity, manufacture a new entity with a :db/excise attribute pointing to that entity's id.  For example, if user 42 requests that his personal data be removed from the system, the transaction data would be:

[{:db/id #db/id[db.part/user],
  :db/excise 42}]

Since :db.excise/attrs is not specified in the transaction data above, all datoms about entity 42 will be excised.

Example: Excising a Window in Time

To excise old values of a particular attribute, you can create an excision for the attribute you want to eliminate, and then limit the excision using either before or beforeT.  Imagine tracking application events that have users, categories, and details.  Your application produces a ton of events, but you don't care about the old ones.  Here is a transaction that will excise all the pre-2012 events:

  [{:db/id #db/id[db.part/user],
    :db/excise :event/user
    :db.excise/before #inst "2012"}
   {:db/id #db/id[db.part/user],
    :db/excise :event/category
    :db.excise/before #inst "2012"}
   {:db/id #db/id[db.part/user],
    :db/excise :event/description
    :db.excise/before #inst "2012"}]

Remembering That You Forgot

It is a key value proposition of Datomic that you can tell not only what you know, but how you came to know it.  This seems to be at odds with excision: if you remember what you forgot, then you didn't really forget it!

You cannot remember what you forgot, but you can remember that you forgot.  Excise attributes are ordinary attributes in the database, and you can query them.  The following query would tell you if datoms about entity 42 have ever been excised:

[:find ?e :where [?e :db/excise 42]]

Once you find those entities, you can of course use the entity API to navigate to the specific attribute and before filters of the excisions.

Excise attributes are protected from excision, so you cannot erase your tracks.  (Other important datoms such as schema are also protected, see the documentation for full details.)

Handle With Care

Excision is different from any other operation in Datomic.  While excision requests are transactions, excision itself is not transactional.  Excision will happen on the next indexing job.

Excision is permanent and unrecoverable.  Take a backup before performing significant excisions, and use excision only when your domain requires that you deliberately forget certain data.  
..

Riak and Couchbase Support


We are pleased to announce today preliminary support for two new storage services for Datomic: Riak and Couchbase.

Riak is an elasticly scalable, distributed, redundant and highly available key-value store in the Dynamo model. It is a great option for Datomic users who want to run such a system system on their own premises (vs e.g. DynamoDB on AWS). Because Riak supports only eventual consistency at this time, a Datomic system running on Riak also utilizes Apache ZooKeeper, a highly-available coordination service. Datomic uses ZooKeeper for transactor failover coordination, and for the handful of keys per database that need to be updated with CAS. The bulk of the data is kept in Riak, immutably, and leverages all of Riak's redundancy and availability characteristics..

Couchbase is an elasticly scalable, distributed and redundant document store. Like Riak, it supports redundant storage. Unlike Riak, it does offer consistency and CAS, trading off for a more conventional availability model, with either manual or automatic failover.

Both solutions are backed with commercial support offerings from the people who make them.

With all three services (Riak, ZooKeeper, Couchbase), Datomic can run on an existing installation alongside other applications without conflict. Thus you can combine your use of Datomic with other uses of the storages, at which they excel. We consider this hybrid use to be highly appealing in practice, as different parts of your applications have different requirements.

As always, you can backup and restore to/from these storages and any other, and switch your application from one storage to another with a change to a different URI.

This makes the set of Datomic storages:

  • In-process memory
  • Transactor-local dev/free mode
  • SQL
  • DynamoDB
  • Riak
  • Couchbase
  • Infinispan


We are very excited about these new options, which greatly expand your choices, especially for non-cloud deployments. Each storage represents different tradeoffs, but what is important is that the choices are yours to make, as you decide what best fits your business and technical requirements.

We look forward to your feedback as we fine tune these integrations for production use.

..

codeq


codeq

Backstory

Programmer Sally: "So, what are you going to do today Bob?"

Programmer Bob: "I'm not happy with the file baz.clj residing in my/ns. So I'm going to go to line 96 and change 2 to 42. I've been thinking about deleting line 124. If I have time, I'm also going to insert some text I've been working on at line 64."

Programmer Sally: (what's wrong with Bob?)

Short Story

codeq ( 'co-deck') is a little application that imports your Git repositories into a Datomic database, then performs language-aware analysis on them, extending the Git model down from the file to the code quantum (codeq) level, and up across repos. By doing so, codeq allows you to:

  • Track change at the program unit level (e.g. function and method definitions)
  • Query your programs and libraries declaratively, with the same cognitive units and names you use while programming
  • Query across repos

The resulting database is highly programmable, and can serve as infrastructure for editors, IDEs, code browsing, analysis and documentation tools.

codeq is open source (EPL), and on github. It works with Datomic Free.

Long Story

We love Git. We use it, and by now so do most of you. Used conservatively, Git provides a good basis for information management (it keeps everything!).

But it is important to understand Git's limits. Without a live connection to the editors, merge tools etc that munge the files, Git is relegated to simply discovering what has changed in the filesystem, and wisely just stores new stuff, using content-based addressing to determine what is new.

Any further information we get from such a recording of novelty has to be derived. Diffs derive mechanical change information, and tree and file diffs are at the core of Git's facilities.

Language-aware analyses can derive change information co-aligned with program semantics.

How it works

Git looks in directories and finds files, names them by the SHAs of their contents, and encodes their relationship to the enclosing tree by filename. During the import phase, codeq pretty much transfers Git's model intact.

During the analysis phase, codeq looks in files and finds code segments, names them by their SHAs, and encodes their relationship to the enclosing file by line+column location. It further associates them with programmatic names and semantics (e.g. definition, or usage), if possible. We call this semantic segment a codeq.

Thus, one way to understand codeq is as an extension of the git model and tree down to a finer granularity, aligned to program semantics.

codeq Model



In Git, every repo is an island. When trying to understand the interactions across your entire program, including the many libraries it uses, each with their own Git repo, it becomes useful to combine repo information in a single database. The beauty of content-based addressing and globally unique namespacing (as done by e.g. Java and Clojure) is that such merging is conflict-free. So, codeq supports the importation of multiple repos into the same database and keeps them sorted, superimposing a level above the Git model.

In Detail

Now we can consider a particular scenario - a programmer edits a file, changing one function definition and inserting another.

From the Git perspective, the two files are different blobs, with different SHAs, in different trees under the same name. Anything else it tells you about what has changed is done via dynamic diffing, and is usually expressed in terms of lines and blocks of text.

Since we know (some of) these files are programs, and they are stored immutably, it seems worthwhile to perform a one-time analysis in order to track change more finely. codeq will break down the top level of the file into the corresponding program-language units (e.g. for Clojure, mostly function-defining forms). It gives each a SHA (if the block of code has never been seen before). It will then look inside and try to determine what the code is about (in context - since the same code can appear e.g. in different namespaces and thus name different things). The 'meaning' is normally some reference to a namespaced program identity, and for some purpose (definition, use). So a codeq encodes the location of a code segment in a file, and its semantics.

File edit:



After the edit, the analysis finds the identical first 2 segments in the same place in the new file, a new segment following, and then the old 3rd segment in a new location. The file ends with a new code segment, but is 'about' the same thing as the prior 4th segment. As time goes by we can get timelines for program constructs that are independent of the timelines of the files that contain them, and more closely aligned with our work (what's the history of this function definition?)

This importation and analysis is not a one-shot thing. You continue to use Git normally. You can go back later and import your newer changes from Git, or perform new or enhanced analyses.  Due to the first-class nature of Datomic transactions, the codeq database knows what has happened to it, what has been imported, what analyses have been run, what schemas have been installed etc.

Put on a happy interface

Git has a powerful engine - durable persistent data structures with structural sharing and some fast C code that manipulates them. Unfortunately, it is hidden behind a plethora of command line utilities each of which has a boatload of options and a variety of outputs - let's have a parsing party!

If only we had some declarative query technology with elegant support for recursion, we could turn all this tree walking into a piece of cake. Wait! - we can fight 1970's technology with... more 1970's technology - Datalog


(def rules
'[[(node-files ?n ?f) [?n :node/object ?f] [?f :git/type :blob]]
[(node-files ?n ?f) [?n :node/object ?t] [?t :git/type :tree]
[?t :tree/nodes ?n2] (node-files ?n2 ?f)]
[(object-nodes ?o ?n) [?n :node/object ?o]]
[(object-nodes ?o ?n) [?n2 :node/object ?o] [?t :tree/nodes ?n2] (object-nodes ?t ?n)]
[(commit-files ?c ?f) [?c :commit/tree ?root] (node-files ?root ?f)]
[(commit-codeqs ?c ?cq) (commit-files ?c ?f) [?cq :codeq/file ?f]]
[(file-commits ?f ?c) (object-nodes ?f ?n) [?c :commit/tree ?n]]
[(codeq-commits ?cq ?c) [?cq :codeq/file ?f] (file-commits ?f ?c)]])


You can follow along with the schema, but suffice to say, that is all the code you need to:

  • Find all the files referenced by a commit
  • Find all the codeqs referenced by a commit
  • Find all the commits including a file
  • Find all the commits including a codeq

This query uses those rules to find all of the different definitions of the function datomic.codeq.core/commit, and when they were first defined:

(d/q '[:find ?src (min ?date)
:in $ % ?name
:where
[?n :code/name ?name]
[?cq :clj/def ?n]
[?cq :codeq/code ?cs]
[?cs :code/text ?src]
[?cq :codeq/file ?f]
(file-commits ?f ?c)
(?c :commit/authoredAt ?date)]
db rules "datomic.codeq.core/commit")


If you don't know Datalog, it's worth the 11 minutes it will take you to learn it.



I hope this gives you a sense of the motivation for codeq, and some excitement for trying it out. It's still early days, and we are definitely looking for help in enhancing the analysis, integrating with tools, supporting other languages etc.

Have fun!

Rich



..

Datomic Monitoring and Performance

I have just added a new section to the Datomic documentation on monitoring and performance. If you are tuning Datomic, it is a must-read.

I want to call attention in this blog post to one aspect of Datomic monitoring that might not be immediately apparent. Which is that you can use Amazon CloudWatch to monitor any instance of Datomic Pro, regardless of which storage you are using, and regardless of whether you are running any of your processes in the AWS cloud.

Part of the value of a good cloud architecture is being able to mix-and-match the pieces. ..

REST API

I'm pleased to announce that, starting with version 0.8.3488, Datomic now offers a REST API.

There are a number of reasons to do this, first and foremost is that it will now be possible to access Datomic from non-JVM languages.

How does it work?

The command bin/rest will start up a peer which runs as a stand-alone HTTP server. You can access that service from any application using any language and any HTTP library. That's it!


This greatly enhances your architectural options:


Q&A


So, does this make Datomic client-server? 

Yes and no. First off, the 'servers' are themselves peers, so you still get elastic, configuration-free horizontal query scalability by simply starting/stopping more peers. Second, the Datomic model, which substantially mitigates the problems of client-server databases, is faithfully replicated for clients:

  • A peer service can serve more than one database, against more than one storage (Pro)
  • Clients get the same kind of data-driven API as do peers
  • Clients can get repeatable queries, and multiple queries with the same basis
  • Clients get the time-travel as-of and since capabilities, raw access to indexes and ranges
  • Clients can issue multi-datasource queries, and pass data to query
  • Clients can get a push feed of transaction events, via a Server-Sent Events source

Basically, it's just more options. Build full peers in a JVM language or lightweight clients in any language, or any combination.

Do these clients count towards my peer count? 

No. The clients do not run the Datomic peer library, and thus do not count. Each REST service process counts as a peer.

Does this work with Datomic Free? 

Yes it does.

What's the status of the API? 

It's still alpha, as we want to incorporate your feedback.

Are there client libraries for language _______?

Not yet. This is something we hope each language community will help us build.

Where can I get more details?

Check out the REST API docs


We hope you enjoy this new API and the capabilities it affords. As always, we welcome your feedback and input. If you've been on the sidelines waiting for Datomic to come to your favorite language - welcome!

..


12 of 14