[racket] Implementing long polling ajax

From: antoine (antoine.brand at sfr.fr)
Date: Wed Dec 4 13:13:22 EST 2013

Hello,

I was wondering how can i implement a long polling ajax technique (aka
comet) (https://en.wikipedia.org/wiki/Long_polling#Long_polling) using the
web-server lib.

So i need build a servlet that don't directly send a response but hold on in
place and wait for being wake up.

The only solution i ends up is using semaphore:

#lang racket

(require web-server/web-server
         web-server/http
         net/url
	 web-server/managers/none
         (prefix-in seq:
                    web-server/dispatchers/dispatch-sequencer)
         (prefix-in filter:
                    web-server/dispatchers/dispatch-filter)
         web-server/servlet-dispatch)

(provide
 interface-version
 start
 manager)

(define interface-version 'v2)

(define manager
  (create-none-manager
   (lambda (req)
     (response/xexpr
      `(html (head (title "No continuation here"))
             (body (h1 "fycj you biiii")))))))

(define poll-hash (make-hash))

(define (poll1 req)
  (define params (map path/param-path (url-path (request-uri req))))
  (define id (second params))
  (define message (third params))
  (with-handlers ([(lambda (_) #t) (quick-response "fail" (format "There is no ~a" id))])
      (let ([sem (hash-ref poll-hash id)])
        (hash-set! poll-hash id message)
        (semaphore-post sem))
      (quick-response "ok" "message transmitted")))
  
(define (push1 req)
  (define params (map path/param-path (url-path (request-uri req))))
  (define id (first params))
  (define sem (make-semaphore 0))
  (hash-set! poll-hash id sem)
  (semaphore-wait sem)
  (begin0 
    (quick-response
     "ok"
     (hash-ref poll-hash id))
    (hash-remove! poll-hash id)))
    

(serve
 #:port 8080
 #:dispatch 
 (seq:make
  (filter:make
   #rx"/poll"
   (dispatch/servlet poll1))
  (dispatch/servlet push1)))

(do-not-return)

A bit of explanation of the code:

- we hit push1 with a request of type /ID
- there is no response from the server
- we hit poll1 with a request of type /ID/MESSAGE
- this increment the semaphore associated with ID and pass MESSAGE inside the poll-hash
- then the previous push1 request can return

Is there other way to do?

I first think using a continuation, but capture continuation still return
something and don't hold the computation.

What is the cost of using a semaphore?

Thanks you in advance for your responses.

Posted on the users mailing list.