Fork me on GitHub
#datomic
<
2017-07-04
>
devth00:07:27

is there a simple mechanism to ping a transactor from a peer to make sure it's still up? i want to catch :db.error/connection-released The connection has been released errors that sometimes occur when we recreate the database in a non-prod environment

devth00:07:55

maybe sync?

marshall00:07:47

The latest release includes a transactor health check

marshall00:07:07

You could also use something like sync

devth00:07:16

oh, awesome

danielcompton04:07:39

When naming attributes, should cardinality many attributes be plurally named? e.g. for cardinality many, should I use :client/address, or :client/addresses?

pesterhazy07:07:06

Singular I think, you transact [client :client/address address]

pesterhazy07:07:05

I'd check the musicbrainz example for inspiration

pesterhazy09:07:52

musicbrainz uses plural: https://github.com/Datomic/mbrainz-sample/blob/master/schema.edn#L264 so ignore me. Maybe it's just a Datomic version of the old "singular vs plural relations" debate in rdbms

henrik10:07:42

Is it possible/advisable to use with at scale to do optimistic “writes”? Can this be reconciled with reality, when the actual result of the write comes knocking on the door?

hmaurer11:07:50

@henrik newbie to Datomic here, can’t answer your question. However I am curious: in which cases would you feel the need to do optimistic writes?

henrik11:07:11

@hmaurer It’s entirely hypothetical at this point, but the thought struck me. Some people have expressed fears about write performance, so I thought, what if writes are assumed to have succeeded until proven otherwise?

henrik11:07:15

Or does that lead down into the black pit of eventual consistency?

hmaurer11:07:22

@henrik it seems to me that if your write-load is so high that Datomic can’t process them quickly enough and you need optimistic writes to maintain decent user-facing performance, you are in trouble. (disclaimer: uninformed opinion)

hmaurer11:07:54

There might be cases in which you would want optimistic writes (e.g. let a user preview the effects of a change, or testing), but write performance doesn’t seem to be one of them

hmaurer11:07:38

I am curious as to whether what you suggest is doable though

hmaurer11:07:48

If you really wanted to I think you could implement it yourself with the log api (http://docs.datomic.com/log.html)

hmaurer11:07:14

Not sure though…

henrik11:07:17

It might not be entirely necessary, but even so it might be interesting since the vast majority of transactions in a well designed app should succeed in any case. So whatever speed up you get would be gravy, if the effort is small enough.

henrik11:07:21

And then there’s probably the odd transaction where you really want to wait for the round trip, so ideally you should be able to decide per transaction whether to use it or not.

hmaurer11:07:05

True. Let’s see if someone has an answer to this

val_waeselynck11:07:17

@henrik where would you call db.with() ? Peer? Transactor?

henrik11:07:07

@val_waeselynck Peer, right? Call with while simultaneously sending the same thing to the transactor. And once the transactor comes back with a 👍 or 👎, the optimistic aspect of the state would have to be thrown away in lieu of the realistic ditto.

Galaux14:07:33

Hi everyone. I can't get my head around whether I should only transact the parts of my entities that have actually been modified or if I can just pass the whole entity and Datomic manages to only persist datoms that were changed

Galaux14:07:42

I guess the result of a :find will be the same anyway but if Datomic does not remove unmodified datoms then I am going to clutter my storage…

potetm14:07:57

@henrik I mean, that's do-able, assuming the semantics are okay for your use case.

potetm14:07:05

At that point, though, it's not even eventually consistent. It's, "I won't usually lose your data" consistent.

karol.adamiec14:07:35

@gax datomic will diff the transaction and only touch things that it needs to. You can see that easily doing a transaction in repl and then doing it again. The return value will say nothing changed on second run.

potetm14:07:49

Unless you have some kind of scheme to ensure there will be no data loss.

Galaux14:07:47

I will try that just for the sake of experimenting

andrei16:07:57

I am trying out datomic for some of our use-cases and we have the following query:

[:find [(max ?revision) ?id] 
   :where [_ :appRegistry/revisionNumber ?revision]
                [_ :appRegistry/id ?id]]
we try to return all Apps with the highest revision for a given ID, however we only get the app with the highest revision

pesterhazy16:07:56

two queries, one to find the highest revision, one to retrieve all the apps?

andrei16:07:21

so this cannot be done in 1 go ?

pesterhazy16:07:39

I can't say definitely that it cannot be done

pesterhazy16:07:33

but I will say that often the answer with Datomic is to use multiple queries. Remember that the data is often local inside the peer, so the penalty is not as great at with an SQL db

andrei16:07:42

or we could use a subquery

andrei16:07:53

although I did not find a good example on how that works

pesterhazy16:07:53

then you might as well use d/q twice... you'll find it frustrating to try to express complex queries in a single d/q call, especially involving aggregation

andrei16:07:28

@pesterhazy thanks for the clarification

andrei16:07:32

in the java api, if one wants to do a nested query, how do you refer to datomic.api/q? e.g. this use-case https://groups.google.com/forum/#!searchin/datomic/Kieran/datomic/5849yVrza2M/nHe6QZQ7CGYJ

(d/q '[:find (max ?count)
       :where [(datomic.api/q '[:find ?track (count ?artist)
              :where [?track :track/artists ?artist]] $) [[?track ?count]]]]
  (d/db conn))

andrei16:07:16

right now one app uses Peer.query("datalog string")

mss17:07:36

hey there, extreme newbie q that I’d appreciate some help on. trying to establish a unique attribute (user’s email) and use it as an ident in a pull query. code roughly looks like the following:

(d/transact conn
            [{:db/ident       :user/email
              :db/valueType   :db.type/string
              :db/unique      :db.unique/identity
              :db/cardinality :db.cardinality/one
              :db/doc         "A user's email address"}])

(d/transact conn
            [{:user/email ""}])

(d/pull (d/db conn)
        '[*]
        {:user/email ""})
am I doing something wrong here? I’d think that pulling based on a unique ident would return the attributes for that specific user, but maybe I’m mistaken about that

mss17:07:29

figured it out. realized that {:user-email ""} should be a vec, as in [:user-email ""]

henrik19:07:09

@potetm Is it really data loss if it would have been rejected by the db? I guess that's more of a philosophical question than a practical one. Yeah, potentially some kind of "error handling" scheme could be triggered on the delta between the temporary fantasy and the more permanent reality.

val_waeselynck19:07:00

@henrik this could be done, but what would be the point? What reads would the with'ed db serve? To me the point of using with ahead of transact is to ensure the transaction wouldn't violate some invariant.

potetm19:07:37

@henrik assuming you're storing the "temporary fantasy" somewhere stable, and that all transactions are reconcilable, there might not be data loss.

potetm19:07:41

Otherwise there absolutely will be. And not in a philosophical sense. If I understand correctly that is.