Fork me on GitHub
#datomic
<
2017-09-25
>
dimovich09:09:57

I need to generate some invitation codes... Maybe datomic has some built-in functionality for this?

dimovich09:09:21

does some have some examples of this?

augustl11:09:25

datomic doesn't have any built in functions to generate data transactor side that I can think of

hmaurer12:09:13

@dimovich generate it on the peer? is there any particular reason you want Datomic to do it for you?

dominicm12:09:44

@hmaurer I'm guessing to guarantee uniqueness in a distributed system

hmaurer12:09:17

@dominicm a sufficiently long random code should guarantee uniqueness to a high enough degree of certainty, no?

hmaurer12:09:20

e.g. a uuid

dominicm12:09:22

@hmaurer sufficiently high is relative I suppose. Presuming that you want the token to be of a short length due to external constraints, it becomes more complicated.

hmaurer12:09:21

what you could also do is have a :db.unique/value constraint on the invitation code, generate it on the peer, and retry if the transaction fail because of a uniqueness exception

hmaurer12:09:47

(if you expect collisions to be fairly infrequent)

cch114:09:34

Soliciting Help: I’ve got a peer that sets up the schema for a database, and then successfully transacts several additional entities. A client using the client API then connects and tries to query the DB for those entities -but without seeing them. Most suspicious, the client API reports that it can’t even resolve the new schema entity and reports :t 1002 …which to me says the client API does not seen any of the peer’s transactions.

cch115:09:59

Looks like a problem with the peer server communication. If I start a transaction from a client, the transaction is sent off, and the peer server shows it in its logs, but the response from the transactor never appears in the peer server’s logs and the client never gets an answer and eventually times out.

cch115:09:19

Not sure where to look and there are no errors on the peer server.

benh15:09:35

@dimovich if the data has to be generated on the txtor, you can do this in a txtor function

benh15:09:14

I have done thiis to simulate a SQL IDENTITY column before

benh15:09:55

I have a datalog question; I have some datalog that returns tuples; I only want a sample of 10 items; is the any way I can use something like (d/q '[:find (rand 10 [?val1 ?val2])

benh15:09:22

just have to (take 10 (shuffle (d/q '[:find ?val1 ?val2

hmaurer15:09:41

@benha I think your second bit of code is the only option

benh15:09:48

ah well. always worth asking

favila15:09:54

@benha You could try coercing the result to a vector, then use the sample aggregation function

favila15:09:16

however, the whole result is realized in memory all the time anyway, even with sample, so there's no benefit to doing it in the query

favila15:09:59

(except it's possible it's a more efficient impl than shuffle+take)

benh15:09:28

how would I coerce results to a vector ? naive (d/q '[:find (sample 10 [?val1 ?val2]) gets me java.lang.IllegalArgumentException: Argument [?val1 ?val2] in :find is not a variable

favila15:09:10

[(vector ?v1 ?v2) ?r] at the end of your :where

favila15:09:33

then :find [(sample 10 ?r) ...]

favila15:09:45

I don't know that sample will work with vectors

benh15:09:12

Yes. that does work. But makes the code harder to follow

colindresj16:09:32

A few times know I’ve had a datomic entity that needs to serialized in order to include in a web response. I find that I’ve been doing a [:*] pull in those cases, but was wondering if there was a more succinct way to go from datomic entity to hash-map. Any insight?

favila16:09:47

more succinct than a wildcard pull? what are you imagining?

colindresj16:09:46

Only feels a little verbose because I’ve got to have the db available and in our controllers that’s not always the case

colindresj16:09:14

But it’s def not too bad, just wondering if there was something sort of like touch that gives back a hash map

favila16:09:35

When would you not have a db?

favila16:09:01

Are you saying you have an entity map (from d/entity) and you want to pull out of it?

colindresj16:09:44

We’ve kind of got an mvc-like namespace setup where datomic functions interact with the db, then give back the results to the controller. The controller then decides what the web response body should look like. We don’t typically have the db readily available in those controller namespaces

favila16:09:10

what do you have available?

colindresj16:09:04

Usually just some ring related utils and maybe some spec validation stuff

favila16:09:14

what is "results"?

colindresj16:09:37

Typically an entity or collection of entities

favila16:09:47

Entity as in entity-map?

favila16:09:02

You can get the db out with d/entity-db

colindresj16:09:09

Did not know that

favila16:09:11

entity maps are lazy, they all have dbs in them

colindresj16:09:23

Cool, so that would make pulling on the entity much simpler

favila16:09:31

which is why your question didn''t make much sense to me

colindresj16:09:41

Yeah didn’t know that

colindresj16:09:56

I can see why confusing to you armed with that knowledge

favila16:09:57

"I want to pull from the database without a database." huh?

colindresj16:09:23

Yeah it was more like I want to turn a lazy datomic entity into a hash-map

favila16:09:23

d/entity is a map-projection of the datoms in the db

benh16:09:23

would (into {} entity-obj) do the trick?

benh16:09:06

only converts that top level, of course

colindresj16:09:38

Does that work? I feel like I tried that and still got some serialization exception

colindresj16:09:48

I could be wrong though — it was a while back

colindresj16:09:30

Actually remember now, it works as long as there are no references to other entities

favila16:09:42

yes, because those are entity-maps

benh16:09:56

you could use tree.walk to recurse down

benh16:09:24

but then you have to worry about loops

favila16:09:26

I've done generic entity-map to plain map conversions before, it's a little tricky

colindresj16:09:27

Yeah, I feel like pull is really the right thing to do, just wanted to see if there was something else

favila16:09:37

but this was before the pull api existed

favila16:09:40

pull api is much better

souenzzo17:09:37

About pull-api: how to deal with enums? Example: :user/tags is a ref-to-many. I usualy want to send {:user/tags [:tag/1]} to frontend, not {:user/tags[{:db/id 3123}]}. I made some code that replace all {:db/id 1321} that has a ident to this ident. But not sure if there is a better way to deal...

souenzzo17:09:34

something like (d/pull db pattern eid :prefer-idents true)

hmaurer17:09:05

@souenzzo try {:user/tags [:db/ident]}

souenzzo17:09:40

{:user/tags [{:db/ident :tag/1}]} is better then {:user/tags [{:db/id 123456}]} but still not {:user/tags [:tag/1]}...

hmaurer17:09:14

@souenzzo you can transform the map you get to match your desired output format

souenzzo17:09:46

Yep. I do that. But has some odd edge cases..

hmaurer17:09:57

(update result :user/tags map :db/ident)

souenzzo17:09:37

#specter (transform (walker :db/ident) :db/ident x)

souenzzo17:09:11

(all maps that contains a :db/ident, should be trasformed by :db/ident function)...

hmaurer17:09:16

ah yeah, I messed up my code 😛 and spectre is nicer anyway

souenzzo17:09:43

But I reached the case: I have a entitie that is a enum but contains other attributes. Then sometimes I want to see all attr, others I want to use as enum... Once I transform with specter on a default interceptor...

Brendan van der Es19:09:01

Hi all, does anyone know where the :db/fn definition for the :db/add and :db/retract tx functions live? I can't seem to find it in the extent of the respective entities nor in the :db.part/db entity.

favila19:09:28

add and retract are intrinsics

favila19:09:36

there is no fn

favila19:09:44

Think about it: if these were transaction functions, what would they expand to?

Brendan van der Es19:09:31

They could still expand to the actual datom but it does make more sense that the transact function (peer or transactor side) would take care of this.

tengstrand20:09:30

If I want to reconstruct a database with all the old transactions intact, can I do that? If the old database consists of 1000 transactions, do I need to perform 1000 transactions to the empty database too, or is it another way of doing it? Some of the facts need to be filtered out also in the target database so it’s not just a simple dump/backup.

favila21:09:17

You need 1000 transactions, in the same order. You can reconstruct the old transaction times by setting :db/txInstant on each transaction; but you cannot alter transaction times after transacting

souenzzo20:09:41

(defn add-to-tx-data
  [db tx-data]
  (let [{:keys [db-after db-before tempids tx-data]} (d/with db tx-data)
        ids-after (d/q MY-QUERY db-before db-after tx-data)]
    (into tx-data
          (for [id ids-after]
            [:db/add (resolve-id->tempid tempids id) :foo/bar true]))))
Existi some way to do resolve-id->tempid? It shoud look to tempids and if there is a tempid that was "resolved" into this id in transaction, returns this tempid, else return the id.

favila21:09:27

How do you distinguish ids that were issued in the tx?

favila21:09:42

I can't think of a way to do it that doesn't involve being careful about what external ids each entity has

favila21:09:13

perhaps you could check the history of the entities mentioned by each tx and see if there are any other txs in the entity history

souenzzo22:09:06

I get it. I will think in another solution

favila21:09:54

if there are none, it is a new entity id; if not, probably it was resolved to an existing id