Temporal Junction Point —Back to the Future of Content Addressing that Changes
tl;dr
- Each ibGib immutable datum has an
ib^gibcontent address, in which thegibis the hash of theib,data, andrel8nsfields. rel8nsare named links to other ibGib, like other technologies have “links”.- The named
rel8ncalledpastis a specialrel8nthat keeps track of an ibGib’s timeline. - The very first
ib^gibin thispastrel8nis called the “temporal junction point”. It is like the opposite of the HEAD in git, as it is a pointer to the earliest immutable frame instead of (usually) the most recent in a given timeline. - This temporal junction point acts as the “UUID” of an ibGib timeline (which is itself a forked timeline, again very similar to a git branch/fork).
- So each ibGib has a named
rel8nto its ownpast, the first of which uniquely identifies the ibGib’s timeline.
ibGib — The Data Model
The data model has four fields: ib, gib, data, and rel8ns.
ib— free-form text, often used as a name, title, or fast-access metadata. E.g."Friends^ABC...”,"Great Title Here^XYZ...","tag home^QRS...".gib— hash ofib,data,andrel8nsfields. Currently SHA-256.data— internal data map, similar to “value” or “content”.rel8ns— named links to an array of otherib^gib. E.g."past": [ "ib^gib", "ib^ABC...", "ib^XYZ...", "ib^QRS..." ].
Origins of the Data Model
I’ve been shaving the yak on this for the past c. 15 years, so it’s hard to keep track. This particular incarnation started about 3 years ago and was proximally born out of wanting to solve caching issues. I figured I could keep track of the full history of data, similar to event sourcing, but more self-contained without a single “source of truth” stream. This made me think of DNA, and eventually I came up with the current structure. At the time I had no idea about git hashes, or branching timelines, and I certainly had never heard the term “content addressable” or “merkle links” or the like. I was just trying to solve my caching issues, which as many know, is a hard problem.
The basic process that drove the evolution goes like this:
- You want to have a “thing”.
- You can either modify that “thing” and keep its “sameness”.
- Or you can fork the “thing” to create a “new, different thing”.
So, each ibGib has rel8ns (a play on words, similar to forking), with a couple rel8ns being special: past, ancestor, and dna (I’ll get into that some other time). The past and ancestor named rel8ns point to these two possible choices when acting upon a “thing”. If you fork it, then you’re “creating a new thing” timeline, and the past will be empty(ish) but the source ibGib will be an ancestor. If you do anything else to it, like mut8 or rel8 (which adds a rel8n), then the next “thing” that is generated will have in its past the source “thing”.
Temporal Junction Point — Back to the Future!
Now to the point of this post — the Temporal Junction Point that is.
Marty McFly: That’s right, Doc. November 12, 1955.
Doc: Unbelievable, that old Biff could have chosen that particular date. It could mean that that point in time inherently contains some sort of cosmic significance. Almost as if it were the temporal junction point for the entire space-time continuum. On the other hand, it could just be an amazing coincidence.
From IMDB.
If you haven’t seen the Back to the Future movies, please stop reading this and go out and watch the entire trilogy…possibly twice. I’ll wait.
Ok good. Now that you are up to speed, you may be asking yourself: What does this have to do with programming? Well, when first developing the currently live version of www.ibgib.com (GitHub master branch, current Angular 4 rearchitecture branch), I had the issue mentioned in Joe Armstrong’s The Web of Names, section “What about content that Changes?”.
Now I knew, since it was my original driving motivation, that I could harness caching (invalidation/refreshing) with my design approach. At 10,000 feet, the basic architecture is each ibGib I’m interested in, I open and maintain a channel (awesome Phoenix websocket abstraction) for that particular frame of the ibGib’s timeline. But in practice, it became too expensive to open & maintain channels for each and every timeframe. Also, when I would query for the latest version (until I can get a microservice “latest projection” going), I would have to query looking through each and every past iteration of an ibGib to see if it was related. Obviously, this is not feasible.
But instead of an attached UUID as mentioned in the above article, I try to keep all of my data strictly constrained to ibGibs (and their ib^gib “pointers” as I think of them). The gib itself is a hash, but I think of them as Gödelian numbers (part of shaving the yak so long ago). These numbers are by definition “unique”(ish), and at some point that line from Back to the Future came to me. I realized that I could think of the first timeframe of an ibGib as like the “birthdate” of that ibGib.
I quickly realized that it was such an important concept, much like a HEAD in version control, that I had to give it a name (the other hard thing in programming). So why not use the Doc’s verbiage?
So now, I look at the “temporal junction point” first, and then search for all ibGib with that in its past. I connect & disconnect to the temporal junction point’s channel.
It is extremely powerful.
So even if you don’t want to keep all of your data construct’s “links” to its past around, maybe because of constraints or optimizations your dealing with, I highly recommend keeping this one around. Just be sure to include it as part of the input data for the subsequent content evolution hashes and you should be good-to-go.
