This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-07-08
Channels
- # announcements (5)
- # aws (15)
- # babashka (7)
- # beginners (138)
- # bristol-clojurians (2)
- # chlorine-clover (11)
- # cider (9)
- # clara (4)
- # clj-kondo (17)
- # cljsrn (20)
- # clojars (1)
- # clojure (73)
- # clojure-europe (17)
- # clojure-italy (1)
- # clojure-nl (9)
- # clojure-spec (4)
- # clojure-uk (9)
- # clojurescript (43)
- # data-science (1)
- # datomic (87)
- # emacs (2)
- # figwheel-main (30)
- # fulcro (71)
- # helix (2)
- # hugsql (4)
- # jackdaw (5)
- # jobs (3)
- # jobs-discuss (31)
- # juxt (5)
- # kaocha (6)
- # lein-figwheel (16)
- # leiningen (1)
- # luminus (4)
- # malli (2)
- # meander (54)
- # music (8)
- # nrepl (12)
- # observability (28)
- # off-topic (85)
- # pathom (11)
- # re-frame (99)
- # reitit (9)
- # ring (1)
- # rum (6)
- # sci (11)
- # shadow-cljs (102)
- # sql (22)
- # tools-deps (10)
- # vim (65)
- # xtdb (14)
@jaret - my formative years were in the Bay Area, so the Kings and Warriors would be the teams I root for, but I enjoy basketball too much to really care who wins.
but I am not a fan of the Knicks, that’s for sure 🙂
I have a question around bulk data entry. Is it better to transact one large transaction with temp-ids to associate refs or, transact entities which form references first and then transact the rest of the data?
The second option sounds tedious, the first one sounds bulky
Hi. I’m wondering how you would model “friendship” in Datomic (assuming “friendship” is mutual)
@alex-dixon one example of an approach: https://github.com/cognitect-labs/day-of-datomic-cloud/blob/master/tutorial/pull_recursion.clj
@marshall Thanks. So an “add friendship” transaction would need to add two facts: “a is friends with b” and “b is friends with a”?
also, you can pull ref relationships in reverse: https://docs.datomic.com/cloud/query/query-pull.html#reverse-lookup
I think the problem to solve is deduping friendship relationships. You can transact a :friend b and b :friend a and have your read patterns understand that both are equivalent, but when you add/update/remove friend relationships, you want to make sure those updates are consistent and not vulnerable to transaction races
Agreed @favila ^ generally I would leverage the bidirectional ref so you don’t hit that issue
I think using a bidirectional ref may still be vulnerable to read skew unless there’s some canonicalization? I can’t think of a case offhand though
If the relationship is always considered bidirectional, it should be ok. I.e. i cant be friends with you if youre not friends with me
I mean during updates, some ordering of friendship add or remove transactions may end up by failing to remove one of the directions
I sort of have a feature request in mind…which would the addition of tuple value types that are effectively sets…they don’t bring ordereding into their equality semantics. For things like this that aren’t really directional
I don’t think that would help @alex-dixon? where would that assertion live?
;; [0 :user/name "foo"]
;; [1 :user/name "bar"]
;; [2 :friendship/between [0 1]] ; I'd like [0 1] and [1 0] to be equal, but they're treated as different.
;; [2 :friendship/since 1949] ; :friendship exists as a fact independent of :user. There can be facts about it.
Something like that. Part of what I’m looking for also is a way to add information about the “friendship”
I’ve solved it by canonicalizing the A and B parts, or by serializing the relationship consistently
e.g. canonicalization: {:friendship/left (always the entity with the lower identity id) :friendship/right (always the other one)}
Was thinking the same with a tuple type. Do a sort. Make ordering consistent or not matter
nowdays I think the best is to combine this approach with a :friendship/left+right composite tuple--best of both worlds
but if you make that unique, watch out for deletions. when retracting a member of a friendship, you need to remove the friendships they’re involved in first
otherwise you’ll end up with :friendship/left+right [nil something]
and get constraint violations
I kinda wish there was a composite tuple mode that would retract the tuple instead of allowing nil in it
actually on balance it’s probably less trouble to use a value tuple with :friendship/left-id+right-id that you control, as long as reads check friendship/left and friendship/right are nonnull
that allows more flexibility about when precisely you schedule the friendship deletions when deleting users
been a bit since i've done datomic but could a rule easily add the reflexive checking?
the issue is still that you have an entity that you want to be unique by a value which is a set
with the right read patterns and using transaction fns or :db/ensure, you could keep the constraint that only one of these exists, but you can’t model it directly with a unique index without doing tricks like this
Ok. Thanks. I was thinking along those lines but didn’t know if I was missing something. I’m still curious about the possibility of something like a tuple type that would ignore ordering for its equality semantics. It seems that might open up a fact representation that doesn’t require encoding directedness, something like :friendship/between #{a b}, and annotate those with other facts
An alternative approach could be to model friendship as the hash of two hashes, then keep track of that as a identifier of "friendship" between two people.
I am trying to get websockets working with datomic ions. My connection function currently looks like:
clj
(defn add-connection! [id]
(faraday/put-item nil sockets-table
{:connection-id id}))
(defn connect [{:as req :keys [input context]}]
(let [event (json/parse-string input true)
id (-> event :requestContext :connectionId)]
(add-connection! id)
;(str {:status 200})
))
This guide on aws websocket https://aws.amazon.com/blogs/compute/announcing-websocket-apis-in-amazon-api-gateway/ suggests
js
exports.handler = function(event, context, callback) {
var putParams = {
TableName: process.env.TABLE_NAME,
Item: {
connectionId: { S: event.requestContext.connectionId }
}
};
DDB.putItem(putParams, function(err, data) {
callback(null, {
statusCode: err ? 500 : 200,
body: err ? "Failed to connect: " + JSON.stringify(err) : "Connected"
});
});
};
There doesn't seem to be access to this callback function with a datomic ion. This thread https://forum.datomic.com/t/websockets-from-ions/1255 claims to have gotten this working.@mail524 I don't understand what problem you're having, could you describe what you expect to happen that isn't happening?
Hey all, question re: the Ions tutorial: once I’ve deployed my solo-topology, lambda-proxied ion and wired it up to an API gateway, why must I append “/datomic” to the invocation URL (or else get a 403 response)? https://docs.datomic.com/cloud/ions/ions-tutorial.html#deploy-apigw
It seems that any appended path will do. But I want to wire up my own domain, and serve my homepage from the empty path.
:face_palm: resolved - it’s an [API gateway quirk](https://stackoverflow.com/questions/52909329/aws-api-gateway-missing-authentication-token), nothing to do with Ions - apologies for the spam
@joe.lane when I call wscat -c wss://<api-key>.
I get error: Unexpected server response: 502
which is describe here https://stackoverflow.com/questions/57438756/error-unexpected-server-response-502-on-trying-to-connect-to-a-lambda-function
because I am not calling the callback
function the connection does not stay alive. I do successfully get the connection id logged into dynamodb.
@mail524 First, are you sure that you need wss://<api-key>...
and not the <api-id>
? How do you know that URL is correct?
Second, it appears you aren't returning the right thing from your ion. It has nothing to do with callbacks.
Third, are you sure that your call to Faraday is returning with success? Maybe add some calls to cast/event
so you can confirm they are being added?
1. it is the app-id I just called it the wrong thing. I know because I get logging for it in cloudwatch when I connect.
2. I am not sure what to return that may be the problem. I have tried {:status 200}
and (str {:status 200})
.
You should follow the "Set up API Logging Using the API Gateway Console" in the S.O. post and look at what the logs say (different logs than the datomic logs)
It seems to work now by returning (chesire/generate-string {:statusCode 200})
. Got the api gateway logs setup too. Hopefully I can get sockets working entirely without further help. Thanks so much!
Is it possible to query maps with datomic? If so, does anyone know where I could find a simple example? (I see the nested vector example here: https://docs.datomic.com/on-prem/query.html)
Not directly. Datomic datalog can query datasources, which are fundamentally sets of tuples
Like this does: https://github.com/djjolicoeur/datamaps