Fork me on GitHub

@mdhaney I adjusted the datomic adapter for using with datomic cloud, wrote up a bit on what I had to change a while back, let me find it.


The formatting kinda sucks but: Datomic cloud was a while back so a bit hazy and slightly different adapter codebase: • replace `datomic.api` require with `[datomic.client.api :as d]`  • in `replace-ref-types` replace `(comp :db/ident (partial d/entity db) :db/id)` with `(comp :db/ident (partial d/pull db '[*] ) :db/id)`  • replace `pull-*` (`d/pull-many db pattern eid-or-eids)` with `(into [] (map (fn [eid]` `(d/pull db pattern eid))` `eid-or-eids))`  • there was no need to install the transaction functions, define in ns and call quoted in transaction form, db is passed as first arg e.g.: `(ref->ident after) (if (nil? after)` `[[:db/retract (str id) k (ref->ident before)]]` `[['(my-namespace/add-ident (str id) k (ref->ident after))]])`


client API there is no simple way to run (d/connect "datomic:") is a lot easier then "create a aws account with a credit card and create 2 cloudformations" also (d/q '[:find (pull ...)]) should perform better then map pull and while d/entity is nearly instantaneous, d/pull should take 0.1s or 1s in dev mode if you are doing something like, one "pull" for each key in a hash-map it could take ~20s


Yeah this was "get it working" code..


RAD Update: I just pushed a new snapshot of RAD and the demo (develop branch of the demo) that includes report filtering/sorting/pagination. It is mostly complete. Currently it is missing (at least) a way to declare your filtering controls as any more than buttons. This is client-side processing. Server-side filter/sort/pagination is partially supported by just using report parameter, but support for sort/filter UI controls that interact with a server is considered a different feature. The implementation caches the intermediate results (loaded rows -> filtered rows -> sorted rows -> current page). So, changing the filter causes a new sort and page calculation, but changing the sort order doesn’t have to re-run the filters…it can just sort what is already filtered. Pagination is very very fast, since all it has to do is a subvec on the existing sorted items (which is O(1) and structurally shared).

👍 28
😍 4

Really excited about RAD and am currently evaluating it for a new web app based on an existing Datomic Cloud/Ions application. The recent discussions about adapting to Cloud seem awesome, but I'm wondering about if that's the same story for Ions specifically? I haven't dove into RAD enough yet but I can imagine the peer-like characteristics of Ions to be suited to adapt over from the peer-based on-prem code (converting entity api calls, etc., as mentioned above); if there's a hole here for specifically Ions I'd love to eventually be able to contribute as well


I’m not terribly interested in Ions at the moment, but nothing about RAD should limit the usability AFAIK, but it will likely require some adaptation of the server-side code (though most of that is intended to be hooked up by you anyway).


Good to hear, might try to make something more packaged for Ions specifically. Ions interested our company in particular due to how much heavy lifting it does with well versioned deploys, production ready infrastructure with VPC and IAM best practices, and the performance of on-prem peers in a much simpler to setup configuration without worrying about the backing store (post-gres, etc.) In that regard RAD seems to me the perfect piece to complete the full story of full stack rapid application development to deployment. Either way, thanks for all the amazing work on Fulcro/RAD!


@tony.kay there's an issue with had to move the ["js-joda-timezone/dist/js-joda-timezone-10-year-range.min.js"] to the :cljs splice.


Thanks…my bad


I’ve personally found ions to be a bit hit/miss? I don’t feel like the repl development integration is quite there?


@tony.kay It might be worthwhile adding some args checks to defmutation et al? (assuming it won’t generate a runtime penalty) I spent a bunch of time with this not realising the arg order was the issue.

(defmutation signup! [{::db/keys [pool] :as env} {:keys [email password]}]
  (log/info "Signing Up" email)
  {::pc/output [:signup/result]} ...)
Though that could also be my lack of familiarity with fulcro…

Chris O’Donnell16:04:00

Is that a pathom mutation or a fulcro mutation?


Right, exactly….It is unfortunate the Pathom chose the same name but different signature for that.


In terms of error-checking: My macro should report if you did that wrong…you have a pathom macro there.


Huh, I didn’t know that


Give me a sec to check, this is straight out of the fulcro-template btw, I just added in the logging line so that it matched the login defmutation. So when should I use one or the other?


Right, the back-end of the template uses Pathom


Fulcro establishes the overall model. How you implement the server is up to you. I used to provide simple entry point macros for the server, and Pathom came around to server more server-centric EQL parsing needs.


Ok so I should still use the pathom macro on the server?


ok, thanks


Is there a simple way to trigger mutations/queries in the clojure repl for development? Do I need to call them through pathom?

💡 4

in fulcro you can just transact!/load! with the app as the first arg, so it’s repl friendly but if you need to test particular queries it’s probably more convenient to call pathom parser directly, yes


pathom parser is just a function which takes env and query (possibly including mutation)


How do you grab the current env?


i typically only have a http request as external env param and db/config/etc are injected on parser creation, so they’re there already


and typically i’m only concerned with the session id in the request, so i add it manually


just like you’re probably adding it in fulcro ring middleware


Right, but in a repl context where would that be?


well, you can grab it from fulcro state directly, if it’s in there. (app/current-state app) to get the normalized state


then copy it to parser invocation. i doubt it’s possible to avoid copying, as the session is bound to client and parser is on the server though you can also query your database for the session


Hmm, I’m probably missing something then, calling it just gets me invalid expression


Thanks for the help =)…


i assumed you have (require '[com.fulcrologic.fulcro.application :as app]) and app is your fulcro app


then you’re doing something like (-> (app/current-state app) :component/id :session :session/id) depending on where your session is stored


sure, glad to help 🙂


Have there been any changes to Fulcro Inspect? I just noticed that making a mutation Query results in:

  "Mutation not found - {:mutation app.model.session/signup!}"}}
Even though the mutation still runs successfully. The query was generated by pressing the Send to query button in the Network tab.


so i was wondering about this too, turns out mutations were never officially supported in the query tab, hence the name


that said, you can still test out mutations there via the trick you discovered


PRs welcome if you want to improve the experience, should be pretty simple since all the plumbing and IO are already working, just need to display the result


Happy to put something together once I get my head around how things work under the hood, I’m still trying to work out how to use pathom from the repl ;)…


Anyone deploying to heroku? Is the process use uberdeps to create an uberjar?

Chris O’Donnell16:04:10

I tried deploying to heroku a while back and had issues with the low memory limit they put on their lower tier instances.


Hmm, that’s problematic, but I might be able to sidestep that issue, how did you deal with the deps,edn, project.clj setup?

Chris O’Donnell16:04:23

I think I deployed a docker image


Hmm, ok, worthwhile doing if I can’t figure this out, thanks for the tip =)…

Chris O’Donnell16:04:30

That compiles the clojurescript, then builds an uberjar which serves static assets as well as API requests. The docker image runs this uberjar.


I haven't tried to deploy to Heroku yet but if @U0DUNNKT2 is right, then it needs standard-2x dyno instance at least. That's a bit disappointing :)

☝️ 4

I’m trying to work out why that is?


I’ve run a fairly meaty clojure app on heroku for a while on the free tier. What exactly would be taking up all that memory?


The issue at the moment is working out how to reference the $PORT env… Or at the very least why I’m getting:

Execution error (ConnectException) at .PlainSocketImpl/socketConnect (
Connection refused (Connection refused)

Chris O’Donnell17:04:25

(System/getenv "PORT")?


I’ve been trying to use the supported prod.edn:

:org.httpkit.server/config     {:port :env.edn/PORT}
But yea, that might be a decent strategy =)…


Ok, so something weird is going on, I can definitely see that the port is being bound correctly, so what’s causing this:

Execution error (ConnectException) at .PlainSocketImpl/socketConnect (
Connection refused (Connection refused)
@tony.kay Is there some other thing that binds that I should be disabling?


:env.edn/PORT is what I do, and I have had success on Heroku


Yep, that part it seems works.


and this is your app, how would I know what else you’re binding to??? 🙂


[web.1]: -main {:legal-origins #{ localhost}, :org.httpkit.server/config {:port 9942}, :taoensso.timbre/logging-config {:level :info, :ns-whitelist [], :ns-blacklist [datomic.kv-cluster datomic.process-monitor datomic.reconnector2 datomic.common datomic.peer datomic.log datomic.db datomic.slf4j org.projectodd.wunderboss.web.Web shadow.cljs.devtools.server.worker.impl]}, :ring.middleware/defaults-config {:params {:keywordize true, :multipart true, :nested true, :urlencoded true}, :cookies true, :responses {:absolute-redirects true, :content-types true, :default-charset utf-8, :not-modified-responses true}, :static {:resources public}, :session true, :security {:anti-forgery true, :hsts true, :ssl-redirect false, :frame-options :sameorigin, :xss-protection {:enable? true, :mode :block}}, :proxy false}, :database-spec {:jdbc-url postgres://<elided>}}
[web.1]: 20-04-10 18:18:53 4a57a697-9a66-45bf-a38c-c6ba69aadaac INFO [com.fulcrologic.fulcro.server.config:54] - Reading configuration file at  config/defaults.edn
[web.1]: 20-04-10 18:18:53 4a57a697-9a66-45bf-a38c-c6ba69aadaac INFO [com.fulcrologic.fulcro.server.config:54] - Reading configuration file at  config/prod.edn
[web.1]: 20-04-10 18:18:53 4a57a697-9a66-45bf-a38c-c6ba69aadaac INFO [app.server-components.config:17] - Loaded config config/prod.edn
[web.1]: 20-04-10 18:18:53 4a57a697-9a66-45bf-a38c-c6ba69aadaac INFO [app.server-components.config:10] - Configuring Timbre with  {:level :info, :ns-whitelist [], :ns-blacklist ["datomic.kv-cluster" "datomic.process-monitor" "datomic.reconnector2" "datomic.common" "datomic.peer" "datomic.log" "datomic.db" "datomic.slf4j" "org.projectodd.wunderboss.web.Web" "shadow.cljs.devtools.server.worker.impl"]}
[web.1]: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
[web.1]: SLF4J: Defaulting to no-operation (NOP) logger implementation
[web.1]: SLF4J: See  for further details.
[web.1]: Execution error (ConnectException) at .PlainSocketImpl/socketConnect (
[web.1]: Connection refused (Connection refused)
[web.1]: Full report at:
[web.1]: /tmp/clojure-7817785402379241503.edn


😃… I’m trying to create a minimal app based off the fulcro-template


then it is one port


I basically want to get the basics working before doing any serious development


Does it try to bind to datomic?


I’ve not found any references, just datascript


not unless you added that


I’ve not containerized in Heroku, only send an uberjar


which are you doing?


The really annoying thing is that usually I’d debug this by doing a heroku run bash, but calling java -cp fulcro.jar clojure.main -m app.server-main in that drops the connection >_<…


I’ll update my project


Can you run it locally on your machine and have it work via env var?


MacOS Linux or Other?


run it locally, then use lsof -i -n -P to look at network ports allocated by process


Then: On memory usage. That is a JVM constraint. There are definitely ways with modern JVM to reduce overall memory footprint, but it is a very feature-rich env, and GC’d VM systems work best when given lots of RAM (that is just a CS fact). I’ve not experimented with how small you can actually get the JVM to be using the new modules and graalvm support, but I expect the answer is quite good. But again, not an issue specific to Fulcro.


The memory at present doesn’t appear to be an issue? That may change as I get the application running properly, but at present it’s happy to sit between 260 and 420 mb


I’m beginning to wonder if it’s a ssl issue with postgres… Digging into how to force ssl…


Ok figured it out, it seems to be the db connection, now just need to work out how to get that going =)… Thanks everyone.


Ok that’s done working, a new issue, what would cause a 404 on resources? Is there some kind of protection on accessing things? I’m trying alternative urls just to see if something messed up with routing


Ok, interesting, wrap-resources is insufficient, I also have to wrap-files


Fulcro 3.2.1-RC1 on clojars. I’m doing this one as an RC because I did some internal modifications to tx processing. This should not break anything, and I’m running it on RAD already and it seems fine. The major fix here is that transactions that are submitted from within transactions, UISM handlers, and deferred routes are delayed until after the next render frame. This will fix various bugs we’ve seen where you do something like set a busy flag in a mutation then transact! to do the heavy computation, but the heavy computation ends up winning the CPU before the next frame can show your busy state. The fix is largely transparent, but it is trivial to access as an option to transact! if you find you need it for some reason. The docstring of transact! has been updated, and there is a dynamic var that can be bound for contextual usage as well. The primary warning is that if you defer until the next render from the top-level (e.g. an onClick event handler in the DOM), then nothing will happen to cause a render, and you’ll look “stuck”.

🔥 8