[Ur] callbacks from C FFI (again)

Sergey Mironov grrwlf at gmail.com
Mon Dec 16 06:16:15 EST 2013


I couldn't wait and sketched a patch illustrating the idea.

https://raw.github.com/grwlf/urweb-callback/master/1_of_1__Draft__loopback_request_for_internal_http_server.patch
https://raw.github.com/grwlf/urweb-callback/master/Test.ur (a test)

It's for internal http server only, and it is 'quick and dirty' so I'm
just asking for review and discussion of the potential problems. Here
are few I already see there:
- the mimic_request function may run out of stack space if recursion
happens. should I enqueue such requests it in a separate thread?
- mimic_request starts new database transaction while running in the
context of a previous one. is it deadlock-free?
- minimal test works (prints debug message), but server reports
"Database connection initialized" every time mimic_request is called.
why is that?

2013/12/16 Sergey Mironov <grrwlf at gmail.com>:
> I just remember that it's not always possible to query server
> port/host because application may use external web server or proxy, so
> it is not always possible to visit callback url. What I actually want
> is to mimic page request from inside the server without actually
> opening HTTP session, parsing headers, etc. I guess it is not that
> simple currently. Correct me if I'm wrong..
>
> 2013/12/16 Sergey Mironov <grrwlf at gmail.com>:
>> Hi. I'd like to re-open the topic [1] regarding UrWeb callbacks from C
>> code. Imagine the 'anonymous downloader' application, where
>> 1. user logs in and enters the link to download
>> 2. server starts the download task, task runs for hours
>> 3. server sends an email to user when the download finishes
>>
>> Also, imagine that I have two separate UrWeb,library: one for starting
>> downloader threads and one for sending emails. I'd like to glue them
>> together but in order to do so I have to provide the thread with a
>> callback to call UrWeb handler which eventually calls email sender.
>> AFAIK, there is no pre-designed way callback an UrWeb code, so here
>> are my ideas and questions:
>>
>> 1)
>> A simple solution I see is to provide the downloader with an url to
>> trigger completion actions. the code may looks like
>>
>> fun handler (clientId: int) =
>>   email <- queryEmail clientId;
>>   Emailer.sendTo email "Download completed"
>>
>> fun download (u:string) = do
>>   clientId <- newClient;
>>   runThreadWithCallback ("wget " ^ u) (url (handler clientId))
>>
>> Looks like no problems here except a low-level one: C FFI code needs
>> to know not url alone but also the current hostname (127.0.0.1 may
>> work) and the port the server is running on. Is there a safe way to
>> query this information from the runtime?
>>
>> 2)
>> A cool solution: Invent some kind of 'detached thread monad'. the new
>> code would be like
>>
>> fun handler (clientId: int) =
>>   email <- queryEmail clientId;
>>   Emailer.sendTo email "Download completed"
>>
>> fun download (u:string) = do
>>   clientId <- newClient;
>>   runInSeparateThread (fn thread_id =>
>>       u <- execute ("wget " ^ u);
>>       (* other logic in Ur/Web language *)
>>       visit (url (handler clientId))
>>       )
>>
>> where
>>
>> val execute : string -> detached_transaction int
>> val visit: url -> detached_transaction unit
>>
>> are both FFI functions declared in detached_transaction monad. But
>> AFAIK only `transaction' or pure functions are allowed for C FFI.. And
>> worse, this snippet would require runInSeparateThread to call pure
>> anonymous Ur/Web function. So we have to
>> a) allow arbitrary monads in C FFI code
>> b) add support for native [val runInSeparateThread : (int ->
>> detached_transaction unit) -> transaction unit]   I think this would
>> be awesome, is it hard to implement?
>>
>> Regards,
>> Sergey
>>
>> [1] - http://www.impredicative.com/pipermail/ur/2012-September/001227.html



More information about the Ur mailing list