Fork me on GitHub
#datomic
<
2018-05-03
>
folcon14:05:01

How do you reference the current transact? Is it just adding a tempid? I’m trying to add some auditing to my db and I’ve been looking at this -> https://blog.clubhouse.io/auditing-with-reified-transactions-in-datomic-f1ea30610285. They use (d/tempid :db.part/tx), is that just creating a tempid to the transaction id in the same way that an tempid references an entity id?

folcon14:05:28

Thanks, I’ll have a read =)…

folcon14:05:10

So further reading leads me to -> https://docs.datomic.com/cloud/best.html#add-facts-about-transaction-entity. It seems that "datomic.tx" is the txid for the current transaction?

folcon14:05:25

Great, thanks!

octahedrion16:05:23

hey what does it mean when I get

:cognitect.anomalies/busy
when I do a multi-database query on 2 dbs, but when I query each separately it works ?

eraserhd18:05:47

I frequently do this: [?eid1 :foo/bar ?value] [?eid2 :foo/bar ?value] [(!= ?eid1 ?eid2)]. This seems like two passes on the index (I imagine). Is there a better way to do that?

hueyp19:05:08

I have a question around transactor function guarantees — we have a unique v attribute

{:db/ident :foo/id
 :db/valueType :db.type/string
 :db/cardinality :db.cardinality/one
 :db/unique :db.unique/value}

hueyp19:05:24

and we set this id in a transactor function

(fn [db eid]
  (let [n (->> (d/datoms db :avet :foo/id (str "foo" 1))
               (take-while (fn [[e a v t]]
                             (.startsWith ^String v "foo")))
               (count)
               (inc))]
    [[:db/add eid :foo/id (str "foo" n)]]))

hueyp19:05:37

the idea being we start at “foo1” and go from there

hueyp19:05:49

in testing we sometimes get

:db.error/unique-conflict Unique conflict: :foo/id, value: foo2 already held by: 17592213012316 asserted for: 17592213017846

hueyp19:05:20

I’m not sure how to reason about this — could be a bug in my code, or is datoms not supported inside a tx function? the index is eventually consistent?

hueyp19:05:47

(“foo” is actually an argument to the function for full disclosure — we prefix the auto-inc ids)

favila19:05:51

@hueyp possibly you invoke the tx function twice in the same TX on the same entity?

hueyp19:05:35

@favila interesting possibility — that would definitely make sense

hueyp19:05:02

I’m doubtful tho as the previous version of the tx function didn’t use datoms but a query of all :foo/id so would hit the same bug and has never hit it 😜

hueyp19:05:15

its weird because it only sometimes fails

hueyp19:05:21

and our tx’s are pretty consistent in datoms

favila19:05:23

oh, your d/datoms will never see "foo2"

robert-stuttaford19:05:51

shouldn’t it be d/seek-datoms ?

hueyp19:05:52

not seeing “foo2” would do it 🙂

favila19:05:56

isn't the goal here "find the highest count for this attribute plus prefix"?

favila19:05:06

you only match "foo1"

favila19:05:11

you want seek-datoms, not datoms

favila19:05:17

or index-range

hueyp19:05:06

hah — for sure that is what we want

favila19:05:35

if you use index range, you won't have to do an attr check too

hueyp19:05:36

so datoms is already constrained by your supplied components?

favila19:05:53

yes, datoms is "only give me datoms matching this pattern"

favila19:05:04

seek-datoms is "start reading at the first datom that matches this pattern"

favila19:05:11

index-range is in the middle

favila19:05:26

it will not seek past the attribute

hueyp19:05:32

that makes a lot of sense … I was surprised when (d/datoms db :avet :foo/id "foo") returned nothing

hueyp19:05:42

I figured it should just start with the first one having that prefix

hueyp19:05:49

but didn’t question it further

favila19:05:13

be careful with seek-datoms

favila19:05:28

you need to check each index segment not just the one you want

hueyp19:05:31

ah — because I’ll keep going right past :foo/id as the attribute

favila19:05:47

that's why index-range may be a better choice here

favila19:05:20

(index-range db :foo/id "foo" nil) and your take-while

favila19:05:39

if there's no assertions for foo/id at all it will just be empty, not the next attribute

hueyp19:05:40

I read this from the docs “The index is updated periodically in the background and contains datoms sorted in various orders.” and was like “this can’t be true for the client API” but was now questioning my life

hueyp19:05:08

all faith restored

favila19:05:11

@eraserhd I'm pretty sure what you are doing is a true cross join--you really do need to visit every index segment to self-join

favila19:05:32

in SQL it would be the same

favila19:05:19

optimizing it is about choosing whether to bind ?value first or ?eid1 first

eraserhd19:05:42

huh, how would I do that?

hueyp19:05:07

can you rely on (index-range db attrid start end) using :avet?

favila19:05:30

it only uses avet

favila20:05:25

@eraserhd By controlling which var is bound and which free in the previous clauses

eraserhd20:05:29

Ah, but if you are binding two variables in the first clause, there's no way to tell Datomic which way to do it. e.g. seek on eavt, bind v, seek on avet, bind e. Hmm.

eraserhd20:05:38

I've noticed I can't use criterium to benchmark queries, either. It seems to get stuck warming up because, I guess, Datomic periodically inserts new classes?

eraserhd20:05:00

(oh, that could be my other components. Don't trust me on that last one.)