问题
Background
In distributed systems messages can arrive in an out of order fashion. For example if message A is sent at time T1 and message B is sent at T2 there is a chance that B is received before A. This matters for example if A is a message such as "CustomerRegistered" and B is "CustomerUnregistered".
In other databases I'd typically write a tombstone if CustomerUnregistered is received for a customer that is not present in the database. I can then check if this tombstone exists when the CustomerRegistered message is received (and perhaps simply ignore this message depending on use case). I could of course do something similar with Datomic as well but I hope that maybe Datomic can help me so that I don't need to do this.
One potential solution I'm thinking of is this:
Can you perhaps retract a non-existing customer entity (CustomerUnregistered) and later when CustomerRegistered is received the customer entity is written at a time in history before the retraction? It would be neat (I think) if the :db/txInstant
could be set to a timestamp defined in the message.
Question
How would one deal with this scenario in Datomic in an idiomatic way?
回答1:
As a general principle, do not let your application code manipulate :db/txInstant
. :db/txInstant
represents the time at which you learned a fact, not the time at which it happened.
Maybe you should consider un-registration as adding a Datom about a customer (e.g via an instant-typed :customer/unregistered
attribute) instead of retracting the Datoms of that customer (which means: "forget that this customer existed").
However, if retracting the datoms of customer is really the way you want to do things, I'd use a record which prevents the customer registration transaction to take place (which I'd enforce via a transaction function).
来源:https://stackoverflow.com/questions/38930416/dealing-with-out-of-order-messages-stored-in-datomic