rgrinberg / opium

Sinatra like web toolkit for OCaml
MIT License
755 stars 67 forks source link

Example of idiomatic way to pass along a database connection #124

Closed shonfeder closed 4 years ago

shonfeder commented 4 years ago

It would be helpful to users (to me, at least!) to include an example of the intended way to pass a database connection along for access in handlers. I would be happy to contribute this example, but would like to be sure I'm approaching it correctly.

Could someone who has done this before sketch out what the shape of this looks like?

anuragsoni commented 4 years ago

This is an excellent idea. I'm still a little unsure about what's the best way to make the examples easier to discover. I've added a few examples in the examples folder inside the repo but i still regularly see questions that indicate people had trouble finding those.

https://github.com/bobbypriambodo/ocaml-todo-api-example Is what some people have found useful. It might be good to adapt something like that for our use-case. Is your opium app public? If so it could be good to link to some existing applications from the readme that people might want to refer to.

rgrinberg commented 4 years ago

I would suggest to write an appropriate middleware to store the connection.

shonfeder commented 4 years ago

Excellent. That will do nicely! Thanks, @anuragsoni.

I've added a few examples in the examples folder inside the repo but i still regularly see questions that indicate people had trouble finding those.

I've found the examples quite useful. Still, two ideas to improve visibility:

Is your opium app public?

I'm working on a "from scratch" tutorial as a followup to this exchange: https://www.reddit.com/r/ocaml/comments/e50uap/any_relevant_tutorials_on_web_apisservers_in_ocaml/f9hwiil/ (I'm abathologist). It's still a WIP, but I hope to invite feedback and corrections from you and other more experienced devs in this area once it's ready to go. It should include fully functioning code, so might be a good candidate to link from the readme. If you're curious, you can see the in-progress source for the tutorial here https://gitlab.com/shonfeder/ocaml_webapp/blob/master/tutorial.org (that org file builds to an html page that isn't uploaded yet, but which offers nicer formatting and navigability) (Note, it's still pretty rough).

Thanks, @rgrinberg.

I would suggest to write an appropriate middleware to store the connection.

That's along the lines I was expecting. ocaml-todo-api-example is easy to follow, but I don't like the idea of starting the DB connection before the app actually begins executing via run_command. Does it make sense to follow the example of https://github.com/rgrinberg/opium/blob/master/examples/auth_middleware.ml, where the connection would be a value in the env, or is there another means of passing things around that I am overlooking?

anuragsoni commented 4 years ago

The cookie middleware and the auth_middleware example are good references for stashing things in the request's environment using Hmap

shonfeder commented 4 years ago

@anuragsoni Great! You perfectly anticipated and confirmed my followup question to rgrinberg. Your guidance here is much appreciated. Once I get things working for my tutorial, I'll loop back here, to see whether we want to link to that or break out a smaller example for the examples dir.

If you like my suggestions for discoverability of the examples, I'm happy to make a PR.

anuragsoni commented 4 years ago

If you like my suggestions for discoverability of the examples, I'm happy to make a PR.

I like the idea for the improvements to the examples! Right now I publish the api docs in the gh-pages branch, but that can be extended to include some extra write ups related to the examples. We can also think about using mdx or the same setup as the readme, using cppo to have the writeup as markdown files while ensuring that the code blocks inside it stay updated and compile.

Once I get things working for my tutorial, I'll loop back here, to see whether we want to link to that or break out a smaller example for the examples dir.

Thank you for working in this. I'll definitely keep an eye on your tutorial page and contribute there 😄

rgrinberg commented 4 years ago

but I don't like the idea of starting the DB connection before the app actually begins executing via run_command

Indeed, the best way to handle this is to abstract away the raw connection with a connection pool. Connections to a database are a finite resource and need to be shared between requests in practice anyway. Of course, I also suggest that this connection pool connects to the db on demand.

anuragsoni commented 4 years ago

Closing this as we have an example repository linked in the readme now.