ocsigen / eliom

Multi-tier framework for programming web and mobile applications in OCaml.
http://eliom.org
Other
299 stars 53 forks source link

Exampel of using `Eliom_service.register_eliom_module`? #805

Open shonfeder opened 1 day ago

shonfeder commented 1 day ago

I am trying to complete the migration of a simple site to Ocsigen and Eliom. I've nearly completed the migration, but I think I am now running up against the complexity of static liking eliom modules. E.g., trying to run the server defined using Ocsigen_server.start, I hit

Fatal error: exception Failure("This function cannot be called here because it needs information about the request or the site.\nCalled from Eliom_request_info.get_request_cache in file \"src/lib/eliom_request_info.server.ml\" (inlined), line 202, characters 11-33\nCalled from Eliom_reference.Volatile.modify in file \"src/lib/eliom_reference.server.ml\", line 117, characters 34-44\nCalled from Eliom_syntax.client_value in file \"src/lib/eliom_syntax.server.ml\", line 141, characters 2-78\nCalled from Eliom_form.Make_links.a in file \"eliom_form.eliom\", line 125....

I believe I am hitting the problem discussed in https://ocsigen.org/eliom/latest/api/server/Eliom_service#2_StaticloadingofEliommodules . I expect I can eventually figure out how to work around this by trial and error, or studying the implementation, but it would be very helpful if there were an example of how to work around this kind of problem.

shonfeder commented 17 hours ago

I've got a workaround that may be useful to report:

The problem I hit is this: while it is obvious how to register an initialization function, it is not at all obvious (to me) how to get that registered init function to be called.

From digging in to ocsigen a git, it seems like the only time these init functions get called is during the parsing of a configuration file (https://github.com/ocsigen/ocsigenserver/blob/7950e0a462164398a4b6af780d2981b0ab7b2149/src/server/ocsigen_parseconfig.ml#L379-L380). Since I am trying to port an existing site (that used opium), and have been trying to use the (iiuc) newer "static" API via Ocsigen_server.start I don't have any such config file to parse. As such, my init function is never getting called.

Based on the docs, I tried to add various XML values to a config file, hoping to get the init function triggered, using ~configfile label to tell start where to find it, but the file was either ignored of failed silently.

Ultimately, this hack fixed the problem for me: https://github.com/shonfeder/ocsigenserver/commit/75c300b11b990f4d594c7e483dc12c3245b60e94

Of course, I lose the nifty dynamic reloading functionality, but this is not worse off than I was before.

It would be very nice to expose the dynamic reloading functionality via the Ocsigen_server.start API, without having to add an XML file just for this purpose. However, I also think an API to just tell start which services it needs to register, or which init function it needs to all, would be a user-friendly way to make using the static API easier.

As an example, it would be convenient to be able to call something like:

  Ocsigen_server.start
    ~ports:([`All, port])
    ~init:(my_init_function:unit -> unit)
    [ Ocsigen_server.host ~port
        [ Eliom.run () ]]

Tho I can imagine some APIs that may be even cleaner (e.g., just taking a list of services and registering them).