Avi Bryant has a great post discussing ways of handling state in continuation based web frameworks. It is a difficult problem and at the moment I'm backtracking all state. Unfortunately the method mentioned of serialising sessions holding points to all continuations in the session didn't work with SISC Scheme. It appears to still hold seperate copies of the state in each continuation. I plan to dig into this further when I get some time. I plan to do the 'Snapshot any object' approach.
Avi is also correct in that the block-href function was inspired by Seaside functionality. I originally added a 'call-page' method that enabled calling a 'subroutine' page and returning back to the calling page. I then went through the Seaside tutorial seeing if I could do similar things to Seaside and discovered that 'call-page' was really 'block-href'. Instead of calling 'show' within 'call-page' I just execute the block. Block is really the wrong name for a Lisp framework though. I'm terrible at naming things.
I struck a problem recently whereby I couldn't resume a continuation stored from the persistant store from another browser session if that continuation relied on 'POST' or 'GET' data. Given my previous example:
(define (data-entry)
(let ((data (new-data)))
(show (mk-data-page1 data))
;; (A)
(set-record-field data "name" (get-param "name"))
(show (mk-data-page2 data))
;; (B)
(set-record-field data "address1" (get-param "address1"))
(set-record-field data "address2" (get-param "address2"))
(set-record-field data "address3" (get-param "address3"))
(show (mk-data-page3 data))
;; (C)
(set-record-field data "more_data" (get-param "more_data"))
(hashtable/put! *data* (get-record-field data "id") data)
(data-entry)))
The continuation resumed at point (B) will work if resumed from the current web server and browser session. But if I bookmark it and resume it later it fails as the 'get-param' call could no longer access the POST/GET data from the HTTP request object. I changed the code so that 'show' returns a hashtable of the POST/GET fields. Something like:
(define (data-entry)
(let ((data (new-data)))
(let ((request (show (mk-data-page1 data))))
(set-record-field data "name" (hashtable/get request 'name)))
(let ((request (show (mk-data-page2 data))))
(set-record-field data "address1" (hashtable/get request 'address1))
(set-record-field data "address2" (hashtable/get request 'address2))
(set-record-field data "address3" (hashtable/get request 'address3)))
(let ((request (show (mk-data-page3 data))))
(set-record-field data "more_data" (hashtable/get request 'more_data)))
(hashtable/put! *data* (get-record-field data "id") data)
(data-entry)))
11:15:22 PM
|