Updated Transacting: upsert resolution algorithm (markdown)

Nick Alexander 2017-01-27 11:03:01 -08:00
parent 0a33514d7e
commit f6a76899e6

@ -27,13 +27,15 @@ We partition the set of transaction entities into the following populations.
The population sets are iteratively refined as follows. Each evolutionary step, we do the following:
1. Try to upsert `upserts-e`. For each pair `[a v]`, we search for `[e a v]` in the store. If such a datom exists, we say entities like `[-1 a v]` have upserted, and we "resolve" the temporary ID `-1` to the entid `e`. Next generation, those entities will be in the `inert` population -- they can evolve no further. If such a datom `[e a v]` does not exist, we say entities like `[-1 a v]` require allocation. Next generation, those entities will be in the `allocations-e` population.
1. Try to upsert `upserts-e`. For each pair `[a v]`, we search for `[e a v]` in the store. If exactly one such datom exists, we say entities like `[-1 a v]` have upserted, and we "resolve" the temporary ID `-1` to the entid `e`. More than one datom can't exist, since `a` is `:db.unique/identity`. Next generation, those entities will be in the `inert` population -- they can evolve no further. If such a datom `[e a v]` does not exist, we say entities like `[-1 a v]` require allocation. Next generation, those entities will be in the `allocations-e` population.
2. Using the temporary IDs that resolved in the previous step, try to evolve the all populations other than `upserts-e` further. That is, we might be able to evolve an entity `[-1 a -2]` in `upserts-ev` to `[-1 a e]` (in `upserts-e`) or to `[e a -2]` (in `allocations-v`) or event to `[e a v]` (in `inert`) next generation. Similarly, we may be able to evolve:
* some entities in `allocations-ev` to `allocations-e`, `allocations-v`, or `inert`;
* some entities in `allocations-e` to `inert`;
* some entities in `allocations-v` to `inert`.
It is possible for a single temp ID to upsert to more than one entid. As soon as we witness such a conflicting upsert, we fail.
Eventually, the population `upserts-e` will be empty. At this point, we evolve every complex upsert `[-1 a -2]` in `upserts-ev` to `allocations-ev`.
Finally, we allocate new entids for any temporary IDs unresolved in `allocations-ev`, `allocations-e`, and `allocations-v`. We're done!