fulcro

Book: http://book.fulcrologic.com, Community Resources: https://fulcro-community.github.io/, RAD book at http://book.fulcrologic.com/RAD.html
ej 2021-01-17T10:16:40.032700Z

This might not be the right place to ask, but does anyone have an idea of the combined AWS costs associated with running an application of the size/complexity as the Fulcro RAD demo with say ... 10-20 concurrect active users per day? I have never used AWS before, but as far as I can understand, I would need to pay for both Datomic Cloud as the DB, and some kind of EC2 instance for the Fulcro application itself. Excuse me if this question is basically "how long is a fish?", or if I should ask it in the datomic channel instead.

Jakub Holý 2021-01-18T08:22:22.044100Z

The problem with datomic is that the production setup is high-end, which indeed is an overkill for simpler apps. But there is no middle ground between this and solo. Since you already must have the Datomic instance, running Fulcro backend there as an Ion seems the most reasonable. For the frontend, perhaps you can serve if from there or serve it from S3 (perhaps with CloudFront in the front, configured to forward requests for /api to the API Gateway backed by Datomic Ions)

ej 2021-01-19T09:45:02.061400Z

Thank you for your detailed responses! This leaves me with a lot of reading to figure out the best approach.

hmaurer 2021-01-19T21:57:45.061800Z

@endrejoh note that you could also use RAD + a SQL database, if you are not attached to Datomic in particular

hmaurer 2021-01-19T22:00:10.062Z

If you are using a SQL database you could probably get away with a very simple setup of some clojure hosting solution + a managed SQL service

ej 2021-01-19T22:12:35.062200Z

@hmaurer I was under the impression that the SQL plugin was kind of a ... second-class citizen in Fulcro, but I am not sure where I got that idea. I am not tied to Datomic in any way right now, as I am just starting out. I have some more reading to do, it seems. Thank you!

hmaurer 2021-01-19T22:13:37.062400Z

@endrejoh It might be; I wouldn’t be the right person to say (I haven’t used Fulcro in quite a while)! But if you are willing to get your hands dirty I see no reason why you couldn’t get it to work with SQL; it’s just that Datomic is a more natural fit for Pathom & co.

ej 2021-01-19T22:31:52.062800Z

Do you have any thoughts on getting started with Fulcro with an SQL database vs Datomic, @holyjak? Is there a big difference? I think ease of learning, support and developer experience is more important to me than cost of deployment (at least right now), but if the difference between the databases is small (abstracted away?) I might prefer the cost-effective solution. If this question seems dumb, it's because I'm just getting started.

Jakub Holý 2021-01-20T10:58:31.068700Z

You can use either just fine. Personally I use a SQL DB. If you want to use RAD - which you should perhaps avoid until you get familiar with Fulcro itself - then you must know that the SQL adapter is much less developed so auto-generated resolvers and form save middleware might not work always for you. I write all my resolvers manually so for me it is not a problem.

👍 1
tony.kay 2021-01-17T12:25:08.032900Z

Fulcro really has no bearing on that. Datomic cloud has a pricing calculator that includes the ec2 and sw charges. You get discounts for dedicated instances, and solo is cheaper than production.

Henry 2021-01-17T13:46:27.033200Z

In the following code, People is the root. People has a list of Persons. Each Person has an address. I have a quick question: Is it possible to auto normalise the data in the Person component not only with :person/id, but also with :address/id? I understand that there can only be one ident in each component for auto-normalisation to work. However, nesting address to person in this way seems cumbersome and inefficient. I thought about creating an Address component, but then each person would have the same address (or same many addresses if it is to-many). What would be the best way to approach the design of data structure in this scenario? Thanks a lot for helping.

daniel.spaniel 2021-01-17T13:49:59.034800Z

Henry, normally you would do an Address component and then use a join in the address part of person query {:person/address (prim/get-query Address)]}

daniel.spaniel 2021-01-17T13:50:15.035200Z

not sure why you don't want to do that, since this normalizes address and will take care of duplicates

Henry 2021-01-17T13:55:27.038800Z

Yes, that's what I thought too, but as I mentioned, I am trying to wrap my mind around this: wouldn't an Address component give every person the same address?

daniel.spaniel 2021-01-17T13:57:54.039100Z

no, just try it and see

xceno 2021-01-17T14:17:05.039200Z

I started with solo but upgraded to prod soon after. I run everything as datomic ion. It costs around 100-200$/month. You can reduce that price a bit by reducing the load balancer to 1 instance, but you obviously loose the redundancy if you do so. However, I didn't have any problems so far. If you're going to use it professionally, I think reserved instances are the way to go. Also, you can host the SPA on S3, but I personally didn't. I'm on my phone right now, but I can provide you some more details later if you have any more questions

❤️ 1
Henry 2021-01-17T14:49:18.039400Z

Thanks @dansudol for your help. I added the Address component but the question was still unresolved. Therefore, I used merge-component! to check, and you're right, the data structure worked well. I then realised that my question actually pertained to the initial-state. For now, both [:person/id 1] and [:person/id 2] have [:address/id 1]. How can you for example add [:address/id 2] to [:person/id 2] in the initial-state?

Jakub Holý 2021-01-18T08:26:31.044300Z

FYI it is preferable to use the https://book.fulcrologic.com/#_template_mode - it is simpler and has some error checking

Jakub Holý 2021-01-18T08:30:13.044500Z

When saying "the same address" did you mean the last line in

:initial-state (fn [{:keys [id name]}] {:person/id      id
                                           :person/name    name
                                           :person/address (comp/get-initial-state Address
                                                             {:id 1 :street "Sweet Street"})})}
? You can pass to this initial state also params for the address, nothing stops you from that. In the template form:
:initial-state {:person/id      :param/id                                      :person/name    :param/name                                           :person/address {:id :param/address-id 1 :param/address-street "Sweet Street"}})}
Though of course in practice you don't need complex state initialization in init state b/c you load the data from a server. Or use the lambda form and return some random data. Depending on what you need.

daniel.spaniel 2021-01-17T16:00:13.040600Z

gee .. i don't know .. maybe in the Person component in the initial-state fn instead of just keys for id and name .. add address and then pass in the same address over and over again. and you could define the address map as a def sweet-street and then reuse it

👹 1
ej 2021-01-17T17:48:20.040800Z

Ah, this is very interesting, @rob703. I did not know that you could run Fulcro on Datomic Ion. So that means both the database and the server is running there, and you have the frontend running somewhere else? Which EC2 instance type are you running, or do you use one for DB and one for server? On the Datomic price calculator it says they recommend i3.large, which seems a little bit overkill for my needs, but what do I know. :)

xceno 2021-01-17T23:58:38.041Z

Disclaimer... I'm working on a proof of concept with just a hand full of users and the hope to get some funding so we can make a real product out of what I do, so please keep that mind. i3.large is overkill for small projects yes, however after fighting with the initial setup for days (due to missing docs, etc.) I decided to call it a day and switch over to a production setup. With this setup you get the http-gateway which allows for "ionizing" your web-apps. I did this because I'm basically the only dev right now and only have so much time to care for infrastructure stuff - so for me it was essential that i could just "ion-push" a release and let datomic cloud handle everything else for me. To save some costs I changed the autoscale capacity to 1 server. In practice this comes down to 5 minutes of unavailability of my system when you push a new release. As for serving your fulcro SPA: When you look at the RAD demo, making a release build of your frontend will put a bundle in your resources folder, and your ionized ring-handler serves it: https://github.com/fulcrologic/fulcro-rad-demo/blob/datomic-cloud/src/shared/com/example/components/ring_middleware.clj#L30 So to finally answer your question: My backend runs on a single EC2 i3.large instance, talks to my datomic db and serves my Fulcro SPA. You have to extend the RAD authorization system though, or replace it with whatever else you need (AWS cognito for example). I thought about writing a guide to my current setup, but it's not entirely "production ready" and I fear that people will just run with it anyway. But here are some things I found along the way: • https://jacobobryant.com/post/2019/ion/https://github.com/jacobobryant/flexbudgethttps://forum.datomic.com/t/solved-ionize-does-not-handle-responses-with-a-body-of-type-file/1018https://docs.datomic.com/cloud/operation/access-control.html#authorize-ionshttps://theconsultingcto.com/posts/http-direct-with-datomic-and-terraform/