Re: [racket-users] Re: Let's organize a Scheme European Event at FOSDEM 2019

2018-10-13 Thread 韋嘉誠
Looks like the https://fosdem.org/2019/schedule/track/minimalistic_languages/
devroom came through!

Unfortunately, http://community.schemewiki.org/?FOSDEM2019 has been
down for days. Anyone know who is running it, and what the status is
on recovering?

-- 
   /c
On Sat, Sep 1, 2018 at 8:34 PM amz3  wrote:
>
>
>
> On Friday, August 24, 2018 at 6:59:43 PM UTC+2, amz3 wrote:
>>
>> Hello Racketeers,
>>
>> Let's organize a Scheme event at FOSDEM 2019 in Bruxelles.
>
>
> Thanks for answering the call.
>
> The devroom proposal will filled be under the 'minimalistic language devroom' 
> name.
>
> Ohter ideas included 'small languages for big ideas' or 'fun languages'
>
> I updated the wiki page.
>
> Don't be shy or feel 'not up to the mark'. Let's have fun and share around 
> our favorite languages and tools.
> I could name a hundred things scheme and hundred racket in particular did 
> last year. But I will leave the latter
> to Chris Webber.
>
> http://community.schemewiki.org/?FOSDEM2019
>
> ETA 3 weeks for the room proposal.
>
>
> Best regards,
>
>
> amz3
>
> --
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread Philip McGrath
On Sat, Oct 13, 2018 at 6:32 PM George Neuner  wrote:

> Remember that a continuation is not a simple thing - in order to resume a
> program from a particular point, the entire state of the current call chain
> must be preserved: the globals, the call stack, the thread state, etc. ad
> nauseam.  If you start to consider things like JIT'd code, shared memory,
> message queues, open files, network connections, etc., the list of what
> needs to be preserved is, in theory at least, unbounded.
>

This isn't quite right: continuations close over the values of local (i.e.
lexical) variables, control flow/the call stack, and continuation marks
(most prominently, parameters in the sense of `parameterize`), but they do
not save global or module-level variables or the store in general.

As an illustration, this program prints the serialized form of one of
`#lang web-server`'s continuations. You can see that the serialized
representation includes `'lexical-value` but not `'global-value`.

#lang web-server

(require racket/serialize)

(define global
  'global-value)

(call-with-web-prompt
 (λ ()
   (let ([lexical 'lexical-value])
 (call-with-serializable-current-continuation
  (λ (k)
(println (serialize k
 lexical)))

But now imagine that 10 different threads have entered that same call chain
> and reached that same continuation point.  Now 10 separate instances of the
> call stacks - and everything they reference - have to be preserved to
> support the continuations.
>

On the same note, I think this depends on what you mean by "reference". If
each continuation closes over a reference to the same shared data
structure, the shared value shouldn't be copied. On the other hand, if they
construct 10 equivalent values (`equal?` but not `eq?`), then yes, all 10
will be retained, just as if you'd stored them in a mutable hash table
without continuations involved.


> Heavy use of "long-lived" [for some definition of "long"] continuations in
> a program can eat up huge amounts of memory.
>

Despite what I just said, I know that stateful servlets do use a lot of
memory to retain native continuations in memory: the "Automatically RESTful
Web Applications" paper says that stateless servlets use ≤10% of the memory
of stateful equivalents.


> Web continuations are kin to general (call/cc) continuations.
>

The stateful web primitives are implemented using `call/cc` and native
continuations. The stateless versions use
`call-with-serializable-current-continuation` and the serializable
representation of continuations from `#lang web-server`.


> So in the scenario above, the state of threads that are [arbitrarily long]
> waiting on user actions might be GC'd to free up memory.
>

 I think this is what you're saying, but, to be totally clear, with
stateless `#lang web-server` servlets, all server-side state is freed once
the response is sent to the client. (Of course, you can still mutate global
state, write to files or databases, etc. by stepping outside of the
continuation system, but you don't need to do any of those things.)

-Philip

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread George Neuner

Hi Marc,

On 10/13/2018 3:37 PM, Marc Kaufmann wrote:

Hi George,

thanks, this is incredibly helpful.

On Sat, Oct 13, 2018 at 9:11 PM George Neuner > wrote:


:

3) results from the initial search are written into a dedicated
table in the database.  The Racket program uses the same
continuation scheme and reads out pages of results on demand as in
(2).  Now, since each database query is self contained, and the
user session does not require a persistent DB connection, a larger
number of users can be serviced with a small(er) pool of
connections.  As in (2), all the result data is transitory in the
Racket program, so all that needs to be remembered are the
continuations.

4) results are written into a dedicated table as in (3).  The
Racket program does NOT use continuations, but rather provides a
dedicated result fetch function - separate from the search
function - and generates page URLs which call that function with
appropriate arguments.  Now, in addition to every DBMS query being
self contained, the functions of the Racket application also are
self contained - there is no persistent session state in the
Racket program.


OK, this does give one nice usecase where the distinction is clear. In 
step 4, how should I think of the dedicated fetch function? Say I type 
"continuations web servers racket" in the search, I get 3 pages, and 
the dedicated table has three pages of 10 results each. Then the 
search spits back the first page, as well as a function created on the 
fly that, if provided with argument `page equal to 2 spits out the 
second page, and if equal to 3 spits out the third? And the reason 
this takes less space than a continuation for each page is what? I 
guess it only needs to know the table location and page number, so if 
there are 10 or 100 pages of results, the function still takes the 
same amount of space, while I have 10 or 100 continuations. Is that 
the difference with scenario 3)?


Yes.

Remember that a continuation is not a simple thing - in order to resume 
a program from a particular point, the entire state of the current call 
chain must be preserved: the globals, the call stack, the thread state, 
etc. ad nauseam.  If you start to consider things like JIT'd code, 
shared memory, message queues, open files, network connections, etc., 
the list of what needs to be preserved is, in theory at least, unbounded.


Imagine that at the point where the continuation is created, the program 
is many levels deep in nested function calls, and many KB of data are on 
the stack or referenced by it.  10 continuations taken at that same 
location AND IN that same call chain won't add much because most of the 
state is shared among them (only the resume location might be 
different).  In the stateful program, each continuation descriptor would 
be just a small structure containing a handful of pointers to objects in 
memory.


But now imagine that 10 different threads have entered that same call 
chain and reached that same continuation point.  Now 10 separate 
instances of the call stacks - and everything they reference - have to 
be preserved to support the continuations.


Heavy use of "long-lived" [for some definition of "long"] continuations 
in a program can eat up huge amounts of memory.  The type of 
continuation involved doesn't really matter - you can get into trouble 
using just upward "escape" continuations (let/ec) as readily as you can 
using general continuations (call/cc).  Obviously you can "escape" with 
a general continuation, but the typical usage of let/ec differs 
substantially from the typical use of call/cc.]



Web continuations are kin to general (call/cc) continuations. Compiling 
with the web-server language performs a number of transformations on the 
program which make it possible to serialize continuation state and 
save/restore it as needed.  So in the scenario above, the state of 
threads that are [arbitrarily long] waiting on user actions might be 
GC'd to free up memory.



George

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread Philip McGrath
On Sat, Oct 13, 2018 at 4:02 PM Marc Kaufmann 
wrote:

> If I understand correctly, the stateful servlet stores the continuation in
> the RAM directly (probably in a form that is not that different from the
> serialized one, but slightly more efficiently?), while the stateless
> servlet writes serialized versions to the disk - which also somewhat limits
> what can get stored in a continuation, since not everything is
> serializeable.
>

This is correct, with the caveat that the representation of a serializable
continuation is actually very different from a "native" continuation (i.e.
what you get with `call/cc` in `#lang racket`). You don't actually need to
know these details, but native continuations are a primitive datatype
provided by the runtime system, essentially like closures. The `#lang
web-server` compiler re-writes your module into continuation-passing style,
so that every continuation is explicit. Then it replaces the continuation
lambdas with serializable structs. In principle, you can think of it as
turning a program like this:
> (define ((make-adder x) y)
(+ x y))
> ((make-adder 2) 40)
42
into:
> (serializable-struct adder (x)
#:property prop:procedure
(λ (this y)
  (+ (adder-x this) y)))
> ((adder 2) 40)
42

This is where the restriction on what can be stored in a serialized
continuation comes from: the contents of the closure turn into fields of a
struct, so you can only close over serializable values. On the other hand,
it's fine to work with non-serializable data: you just can't store it in
the continuation across interactions. (In fact, I sometimes intentionally
make structs non-serializable when I want to make sure I don't retain them
across interactions.)

So only the servlet.rkt (where I start the server) should be in `#lang
> web-server`? That sounds fine.
>

I think you may have gotten that backwards: the module(s) where you
*implement* the servlet—e.g. anywhere you use `send/suspend`—need to be in
`#lang web-server`. The module where you actually start the server (with
`serve/servlet` or equivalent), nor do any libraries you use. To be
concrete, here's an example:

#lang racket

(module servlet web-server/lang
  ;; equivalent to #lang web-server
  (provide start)
  (define (start req)
(let loop ([n 0])
  (send/suspend
   (lambda (k-url)
 (response/xexpr
  `(html (head (title "Example Servlet"))
 (body
  (h1 ,(number->string n))
  (p (a ([href ,k-url])
"Add 1")))
  (loop (add1 n)

(module* main racket
  (require web-server/servlet-env
   (submod ".." servlet))
  (serve/servlet start #:stateless? #t))

There is a more specific way to define "the module(s) where you implement
the servlet" to take into account the other requirement of `#lang
web-server`, which is that you can only capture continuations inside
"transformed contexts". There is a simple example in the docs
,
and lots of discussion in the papers, but I basically recommend that you
ignore this until you get an error message. I found it extremely confusing
when I was getting started, and it sent me down the wrong path in debugging
several times, but it has never actually been a problem for me.

Personally, I had experience with RESTful web programming before I came to
>> Racket, and I also started using stateless servlets first. Once it finally
>> clicked, stateless servlets/serializable continuations made sense to me,
>> and I could see that what `#lang web-server` does automatically is really
>> just what I had previously been doing manually and painfully: stuffing all
>> of the data needed to continue the interaction into URL query parameters,
>> hidden form fields, etc.
>>
>
> This! I used to do this all the time and still sometimes do, but recently
> replaced it by continuations. (Thanks to Matthew Butterick's write-up on
> continuations btw, which made them click for me.) However, I ended up with
> n parameters: one for period, one for id, one for phase of the moon, ...
> Every time I changed the code or realized I needed one more state variable,
> I had to refactor all the instances, until it occurred to me to define a
> `struct my-struct and pass that around and then the only place I have to
> change it is in the struct when adding new variables. I know, this should
> have been obvious, but while trying to figure out how to get the
> continuation working, I didn't consciously grasp that all I was doing was
> passing state around, the same way that big-bang in HTDP/2e does it. That
> was a real missing-the-forest-for-the-trees moment for me.
>

I wish I knew how to write something that would reproduce the epiphany
moment I had with this for others. Even after I'd come to Racket, I found
the web server stuff strange and foreign at first and started out using
`net/cgi`, because I already knew how CGI worke

Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread Philip McGrath
On Sat, Oct 13, 2018 at 3:11 PM George Neuner  wrote:

> The web-server language helps in conserving memory because its
> continuations can be serialized - stored in files, or in databases, etc. -
> and so the program's continuation state(s) can be persisted to disk rather
> than memory as in a stateful #lang racket program.  For that ability, the
> program necessarily becomes a bit more more complicated (stuffers, etc.).
>

I would be interested to hear in what way you have found stateless `#lang
web-server` servlets more complicated than stateful ones. That hasn't been
my experience, though, as I said, I've used stateless servlets much more
extensively than stateful ones.

In particular, I haven't found stuffers a source of complexity at all. The
only time when I've really had to fiddle with the stuffer at all is when
there are security considerations and I need to guard against forged urls,
but the process for doing that is easy and documented (
http://docs.racket-lang.org/web-server/stateless.html#(def._((lib._web-server%2Fstuffers%2Fhmac-sha1..rkt)._.H.M.A.C-.S.H.A1-stuffer))).
In particular, the security consideration is fundamentally the same as for
any RESTful web program: in fact, I would argue that customizing the
stuffer is easier than trying to check against forged query parameters if
writing an equivalent program manually. Still, there is probably room for
improvement. Maybe `make-default-stuffer` could take an optional keyword
argument to make it sign continuations with a given key?

1) The Racket program can read out all the results [freeing up the DB
> connection], send the 1st page of 20 and include continuation links for the
> additional pages.  But there are 59 pages of results, plus  and
>  where applicable.  Even limiting to, say 10 page links at a time
> [like Google], that means 11 or 12 outstanding continuations kept open on
> this one user session.  AND, no good way to decide when to expire them ...
> the user may go off and examine some result(s) for a while, then come back
> to the list.
>

If I understand your example correctly, stateless servlets essentially let
you write your program like #1 and transforms it into something more like
#4 automatically, as long as your representation of search results is
serializable. The data and context for all of the other page links are
serialized as part of the continuation. If small enough, they are all sent
over to the client; otherwise, their saved in hash-addressed storage and
the client gets the hash to find them again. By default the hash-addressed
storage just uses the filesystem, but you could easily adjust the suffer to
use a database instead.

Of course there are still design considerations, and stateless servlets
don't eliminate those any more than manually RESTful web programming does.
In particular, if the search results might change due to external events
(e.g. the library purchases a new book), you have to decide what to do
about that.


> And cookies can be used to store user session state rather than encoding
> it into URLs (continuation based or not).
>

Just a word of caution here that cookies may or may not be the right notion
of state for a given application: sometimes you really want the semantics
of "web cells" (see "Interaction-Safe State for the Web",
http://scheme2006.cs.uchicago.edu/03-mccarthy.pdf and "Implementation and
Use of the PLT Scheme Web Server",
http://cs.brown.edu/~sk/Publications/Papers/Published/khmgpf-impl-use-plt-web-server-journal/paper.pdf).
I will say that it took me several readings of these papers to get my head
around the ideas well enough to use them, but there I still run into
commercial web applications that use the wrong kind of state.

-Philip

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread Marc Kaufmann
On Sat, Oct 13, 2018 at 8:45 PM Philip McGrath 
wrote:

> "Stateless servlets avoid this issue by making continuations serializable,
>> so they can be saved on the client, in a database, etc."
>> Does this mean I have to deal with managing them myself?
>>
>
> No, `#lang web-server` will manage the continuations for you, just as
> stateful servlets do. There is a hook to configure exactly how
> continuations are serialized by providing your own "stuffer," but you don't
> need that to get started. (You should look at the security considerations
> before you go live, but those are easy to deal with if they are relevant to
> your application.)
>
>
Deal with security later has been my mantra since the start...

I did skim the page on stateless servers, but I don't understand who the
>> web server should provide interface-version, stuffer, and start to. Do I
>> have to require this file in all the *.rkt files that uses
>> send/suspend/dispatch?
>>
>
> I had forgotten how confusing I had found the web server documentation
> when I first encountered it. You don't actually need to provide any of
> those things: that part of the documentation, as I understand it, is
> referring to the old (i.e. before my time) way of running servlets before
> `serve/servlet`, `dispatch/servlet`, etc. existed.
>
>
That's good to know. Which reminds me: for future readers (including
probably myself) who are confused by what `serializeable` means, here's
Wikipedia:

"*serialization* is the process of translating data structures
 or object
 state into a
format that can be stored (for example, in a file
 or memory buffer
) or transmitted (for example,
across a network 
connection link) and reconstructed later (possibly in a different computer
environment)."

If I understand correctly, the stateful servlet stores the continuation in
the RAM directly (probably in a form that is not that different from the
serialized one, but slightly more efficiently?), while the stateless
servlet writes serialized versions to the disk - which also somewhat limits
what can get stored in a continuation, since not everything is
serializeable.

As a practical matter, you can start to go stateless just by substituting
>> #lang web-server  for  #lang racket ... odds are that most/all of your
>> program will remain the same.  The web-server language enables you to do
>> things beyond what a stateful Racket server can do, but you don't need to
>> worry about cells and stuffers, etc. until / unless you really need them.
>>
>
> To be a little more specific, `#lang web-server` does two things:
>
>1. It performs a transformation on modules written in `#lang
>web-server` to make continuations within those modules serializable. (It
>also makes anonymous functions serializable.)
>2. It provides alternative versions of web interaction primitives like
>`send/suspend` that work with serializable continuations instead of the
>stateful infrastructure.
>
> #2 means that, in addition to using `#lang web-server`, you need to remove
> `(require web-server/servlet)`, lest the stateful primitives shadow the
> stateless ones.
>
> #1 does *not* mean that you need to use `#lang web-server` for all of
> your modules: in particular, the module in which you call `serve/servlet`
> or `dispatch/servlet` does not necessarily need to be in  `#lang
> web-server`.
>
>
So only the servlet.rkt (where I start the server) should be in `#lang
web-server`? That sounds fine.

In addition, you need to provide a non-false `#:stateless?` argument to
> `serve/servlet` or `dispatch/servlet` to make it set up the context for a
> stateless servlet instead of a stateful one.
>
>
Thanks, this almost surely saved me 15-120 minutes of headscratching.

I have a mixture of both (for no good reason that I couldn't figure out how
>> to do some parts with continuations after starting with them, due to
>> wanting to learn how to use them), but realized that if I hit an error and
>> have to restart the server, all existing users are going to see 'Page
>> expired' links, which isn't Very Good (TM) even by my standards - or
>> especially, since I usually do hit bugs that I have to fix after going live.
>>
>
> Stateless servlets address this problem: serialized continuations remain
> valid across server restarts, multiple servers running behind a load
> balancer, etc. There is a mechanism that renders serialized continuations
> invalid if the relevant source code changes, which is a good thing: the
> potential bugs otherwise would be nightmarish.
>
>
Another problem solved, and together with George's explanation I finally
see what the difference is between the stateful and stateless server.

Is there somewhere a good write-up on a comparison of what is nice abou

Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread Marc Kaufmann
Hi George,

thanks, this is incredibly helpful.

On Sat, Oct 13, 2018 at 9:11 PM George Neuner  wrote:

> Hi Marc,
>
> On 10/13/2018 12:17 PM, Marc Kaufmann wrote:
>
>
> On Sat, Oct 13, 2018 at 5:49 PM George Neuner 
> wrote:
>
>>
>> When the program is operating normally, are you seeing *different*
>> continuation URLs every time you execute the same send/suspend/... call?
>> Or are all the URLs for the same send/suspend/... call identical?   IIRC,
>> the default URL generator includes a nonce, but you can create your own
>> URLs.
>>
>>
> The urls have different numbers at the end of the form (("k" . "(6 1
> 8431734)")) if that's what you mean by nonce.
>
>
> Yes.  A "nonce" is (supposed to be) a single use, never repeated, stamp.
> Obviously the "never repeated" part is impractical with reasonably sized
> numbers (rollover), but the point is to generate a unique value that won't
> be repeated within the expected lifetime of the continuation.
>
>
> I generally use stateful servers myself, because I don't use web
>> continuations.  It's not that I don't like them - it's that I don't often
>> have a need for them that isn't better served by using a database.  I
>> certainly do use continuations in my programming - I just don't use web
>> continuations.  I do think that long duration web continuations are a
>> questionable design ... there are just too many error possibilities in the
>> web environment.  Short-lived continuations?  Up to a few minutes?  Maybe
>> ... but I'd need a good use case to justify them.
>>
>
> To clarify, when you say you use a database you mean when the form gets
> posted, there is some variable in the database (say 'page_number') that
> gets incremented, then after the storing in the database, you check the
> database for the page and see the variable is one larger and you post the
> next page? Whereas with continuations there is nothing in the database that
> I can see and the new page is the continuation, as in (generate-page (+ n
> 1))?
>
>
> Not exactly, although that is a valid use case.  The more concurrent
> users, the more it makes sense to use a database to hold session state.
>
>
> My canon example is a database search engine [my own application area].
> User submits search criteria, and [like Google,etc.] gets back a list of
> results.  But say the user wants the results (no more than) 20 per page and
> there are 1172 results.  Now there are some choices about how to structure
> the ongoing session with the user.
>
> 1) The Racket program can read out all the results [freeing up the DB
> connection], send the 1st page of 20 and include continuation links for the
> additional pages.  But there are 59 pages of results, plus  and
>  where applicable.  Even limiting to, say 10 page links at a time
> [like Google], that means 11 or 12 outstanding continuations kept open on
> this one user session.  AND, no good way to decide when to expire them ...
> the user may go off and examine some result(s) for a while, then come back
> to the list.
>
> Keep in mind that (presumably) there will be some number of concurrent
> users doing similar things.
>
> 2) The Racket program can hold a cursor open on the DB results, use the
> same continuation scheme as above, and read out just a page full of results
> on demand when the user wants them.  This approach has the same
> continuations open, and adds a persistent DB connection, but it shifts the
> load of caching results to the DBMS ... result data passing through the
> Racket program now is transitory and can be GC'd if memory is needed.
>
> 3) results from the initial search are written into a dedicated table in
> the database.  The Racket program uses the same continuation scheme and
> reads out pages of results on demand as in (2).  Now, since each database
> query is self contained, and the user session does not require a persistent
> DB connection, a larger number of users can be serviced with a small(er)
> pool of connections.  As in (2), all the result data is transitory in the
> Racket program, so all that needs to be remembered are the continuations.
>
> 4) results are written into a dedicated table as in (3).  The Racket
> program does NOT use continuations, but rather provides a dedicated result
> fetch function - separate from the search function - and generates page
> URLs which call that function with appropriate arguments.  Now, in addition
> to every DBMS query being self contained, the functions of the Racket
> application also are self contained - there is no persistent session state
> in the Racket program.
>
>
OK, this does give one nice usecase where the distinction is clear. In step
4, how should I think of the dedicated fetch function? Say I type
"continuations web servers racket" in the search, I get 3 pages, and the
dedicated table has three pages of 10 results each. Then the search spits
back the first page, as well as a function created on the fly that, if
provided with argument `page equal to 2 spits out the s

Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread George Neuner

Hi Marc,

On 10/13/2018 12:17 PM, Marc Kaufmann wrote:


On Sat, Oct 13, 2018 at 5:49 PM George Neuner > wrote:



When the program is operating normally, are you seeing *different*
continuation URLs every time you execute the same send/suspend/...
call?  Or are all the URLs for the same send/suspend/... call
identical?   IIRC, the default URL generator includes a nonce, but
you can create your own URLs.


The urls have different numbers at the end of the form (("k" . "(6 1 
8431734)")) if that's what you mean by nonce.


Yes.  A "nonce" is (supposed to be) a single use, never repeated, 
stamp.  Obviously the "never repeated" part is impractical with 
reasonably sized numbers (rollover), but the point is to generate a 
unique value that won't be repeated within the expected lifetime of the 
continuation.




I generally use stateful servers myself, because I don't use web
continuations.  It's not that I don't like them - it's that I
don't often have a need for them that isn't better served by using
a database.  I certainly do use continuations in my programming -
I just don't use web continuations.  I do think that long duration
web continuations are a questionable design ... there are just too
many error possibilities in the web environment.  Short-lived
continuations?  Up to a few minutes?  Maybe ... but I'd need a
good use case to justify them.


To clarify, when you say you use a database you mean when the form 
gets posted, there is some variable in the database (say 
'page_number') that gets incremented, then after the storing in the 
database, you check the database for the page and see the variable is 
one larger and you post the next page? Whereas with continuations 
there is nothing in the database that I can see and the new page is 
the continuation, as in (generate-page (+ n 1))?


Not exactly, although that is a valid use case.  The more concurrent 
users, the more it makes sense to use a database to hold session state.



My canon example is a database search engine [my own application area].  
User submits search criteria, and [like Google,etc.] gets back a list of 
results.  But say the user wants the results (no more than) 20 per page 
and there are 1172 results.  Now there are some choices about how to 
structure the ongoing session with the user.


1) The Racket program can read out all the results [freeing up the DB 
connection], send the 1st page of 20 and include continuation links for 
the additional pages.  But there are 59 pages of results, plus  
and  where applicable.  Even limiting to, say 10 page links at 
a time [like Google], that means 11 or 12 outstanding continuations kept 
open on this one user session.  AND, no good way to decide when to 
expire them ... the user may go off and examine some result(s) for a 
while, then come back to the list.


Keep in mind that (presumably) there will be some number of concurrent 
users doing similar things.


2) The Racket program can hold a cursor open on the DB results, use the 
same continuation scheme as above, and read out just a page full of 
results on demand when the user wants them.  This approach has the same 
continuations open, and adds a persistent DB connection, but it shifts 
the load of caching results to the DBMS ... result data passing through 
the Racket program now is transitory and can be GC'd if memory is needed.


3) results from the initial search are written into a dedicated table in 
the database.  The Racket program uses the same continuation scheme and 
reads out pages of results on demand as in (2).  Now, since each 
database query is self contained, and the user session does not require 
a persistent DB connection, a larger number of users can be serviced 
with a small(er) pool of connections.  As in (2), all the result data is 
transitory in the Racket program, so all that needs to be remembered are 
the continuations.


4) results are written into a dedicated table as in (3).  The Racket 
program does NOT use continuations, but rather provides a dedicated 
result fetch function - separate from the search function - and 
generates page URLs which call that function with appropriate 
arguments.  Now, in addition to every DBMS query being self contained, 
the functions of the Racket application also are self contained - there 
is no persistent session state in the Racket program.



Obviously, there has to be some way to expire cached results (easily 
accomplished with a  timestamp that can be updated / extended 
if the user keeps accessing the result set).  And cookies can be used to 
store user session state rather than encoding it into URLs (continuation 
based or not).


The object of the exercise really is to minimize the RAM required 
per-user to maintain state on the server, so that you can serve more 
users with the same amount of resources.  Comparatively, disk space for 
yet-another table (or file) essentially is 

Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread Philip McGrath
>
> "Stateless servlets avoid this issue by making continuations serializable,
> so they can be saved on the client, in a database, etc."
> Does this mean I have to deal with managing them myself?
>

No, `#lang web-server` will manage the continuations for you, just as
stateful servlets do. There is a hook to configure exactly how
continuations are serialized by providing your own "stuffer," but you don't
need that to get started. (You should look at the security considerations
before you go live, but those are easy to deal with if they are relevant to
your application.)

I did skim the page on stateless servers, but I don't understand who the
> web server should provide interface-version, stuffer, and start to. Do I
> have to require this file in all the *.rkt files that uses
> send/suspend/dispatch?
>

I had forgotten how confusing I had found the web server documentation when
I first encountered it. You don't actually need to provide any of those
things: that part of the documentation, as I understand it, is referring to
the old (i.e. before my time) way of running servlets before
`serve/servlet`, `dispatch/servlet`, etc. existed.

As a practical matter, you can start to go stateless just by substituting
> #lang web-server  for  #lang racket ... odds are that most/all of your
> program will remain the same.  The web-server language enables you to do
> things beyond what a stateful Racket server can do, but you don't need to
> worry about cells and stuffers, etc. until / unless you really need them.
>

To be a little more specific, `#lang web-server` does two things:

   1. It performs a transformation on modules written in `#lang web-server`
   to make continuations within those modules serializable. (It also makes
   anonymous functions serializable.)
   2. It provides alternative versions of web interaction primitives like
   `send/suspend` that work with serializable continuations instead of the
   stateful infrastructure.

#2 means that, in addition to using `#lang web-server`, you need to remove
`(require web-server/servlet)`, lest the stateful primitives shadow the
stateless ones.

#1 does *not* mean that you need to use `#lang web-server` for all of your
modules: in particular, the module in which you call `serve/servlet` or
`dispatch/servlet` does not necessarily need to be in  `#lang web-server`.

In addition, you need to provide a non-false `#:stateless?` argument to
`serve/servlet` or `dispatch/servlet` to make it set up the context for a
stateless servlet instead of a stateful one.

I have a mixture of both (for no good reason that I couldn't figure out how
> to do some parts with continuations after starting with them, due to
> wanting to learn how to use them), but realized that if I hit an error and
> have to restart the server, all existing users are going to see 'Page
> expired' links, which isn't Very Good (TM) even by my standards - or
> especially, since I usually do hit bugs that I have to fix after going live.
>

Stateless servlets address this problem: serialized continuations remain
valid across server restarts, multiple servers running behind a load
balancer, etc. There is a mechanism that renders serialized continuations
invalid if the relevant source code changes, which is a good thing: the
potential bugs otherwise would be nightmarish.

Is there somewhere a good write-up on a comparison of what is nice about
> one style vs the other? I am not asking which is better, but examples that
> highlight how they are different or lead to different solutions or
> different trade-offs?
>

There is a gap in the documentation, I think. (Maybe I should try to write
some more.) I know that I did find reading Jay's papers helpful, even if
the formal PL parts were over my head:

   - "Automatically RESTful Web Applications: Marking Modular Serializable
   Continuations": https://doi.org/10.1145/1596550.1596594
   - "The Two-State Solution: Native and Serializable Continuations
   Accord":
   https://jeapostrophe.github.io/home/static/oopsla026-mccarthy.pdf

Personally, I had experience with RESTful web programming before I came to
Racket, and I also started using stateless servlets first. Once it finally
clicked, stateless servlets/serializable continuations made sense to me,
and I could see that what `#lang web-server` does automatically is really
just what I had previously been doing manually and painfully: stuffing all
of the data needed to continue the interaction into URL query parameters,
hidden form fields, etc. The benefits of stateless servlets are mostly just
the benefits of not using server-side state in general. The main
disadvantage is that you need to ensure data structures that will be
serialized as part of the closure are serializable. However, while it takes
some practice to get a sense of this (maybe another opportunity for more
documentation), it isn't actually a big problem in practice.

-Philip

On Sat, Oct 13, 2018 at 12:18 PM Marc Kaufmann 
wrote:

>
> On Sat, Oct 13, 2

Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread Marc Kaufmann
On Sat, Oct 13, 2018 at 5:49 PM George Neuner  wrote:

> Hi Marc,
>
> On 10/13/2018 10:42 AM, Marc Kaufmann wrote:
>
> Thanks George and Philip.
>
> George, while I am sure that in some places I allow using continuations
> after a delay, that's not what I meant. What I feel is happening (with
> little evidence, mind you) is that, when I come back to my website after 3
> days and open the homepage, it creates it on the fly with a *new*
> continuation (generated now), yet when the link gets called it gives me
> this error. I would have thought this continuation is new, yet it seems to
> throw the error I am talking about more often when I haven't visited the
> site in a while. See below for the servlet I am using currently, I am not
> specifying a manager.
>
>
> Which means you are using the default manager. That would explain an old
> continuation expiring, but not a new one.
>
> When the program is operating normally, are you seeing *different*
> continuation URLs every time you execute the same send/suspend/... call?
> Or are all the URLs for the same send/suspend/... call identical?   IIRC,
> the default URL generator includes a nonce, but you can create your own
> URLs.
>
>
The urls have different numbers at the end of the form (("k" . "(6 1
8431734)")) if that's what you mean by nonce.

>
> Philip, thanks, I didn't realize that I had made an active choice. I am
> pretty sure I was simply using stateful servlets because the
> send/suspend/dispatch link on "Continue: Web Applications in Racket" links
> to the stateful servlets page, not to the stateless servlets page. If this
> is not best practice, maybe it would be better to link it to the
> send/suspend/dispatch on the stateless server page. You say:
>
> "Stateless servlets avoid this issue by making continuations serializable,
> so they can be saved on the client, in a database, etc."
>
> Does this mean I have to deal with managing them myself?
>
> Practically speaking, since both of you seem to imply that I should use
> stateless servers, how do I do that? I did skim the page on stateless
> servers, but I don't understand who the web server should provide
> interface-version, stuffer, and start to. Do I have to require this file in
> all the *.rkt files that uses send/suspend/dispatch?
>
>
> It's not really a matter of "best practice" ... stateful vs stateless
> mostly is a non-issue unless you have limited memory or you really need web
> continuations to be available long duration: e.g., hours or days.
>
> I generally use stateful servers myself, because I don't use web
> continuations.  It's not that I don't like them - it's that I don't often
> have a need for them that isn't better served by using a database.  I
> certainly do use continuations in my programming - I just don't use web
> continuations.  I do think that long duration web continuations are a
> questionable design ... there are just too many error possibilities in the
> web environment.  Short-lived continuations?  Up to a few minutes?  Maybe
> ... but I'd need a good use case to justify them.
>
>
To clarify, when you say you use a database you mean when the form gets
posted, there is some variable in the database (say 'page_number') that
gets incremented, then after the storing in the database, you check the
database for the page and see the variable is one larger and you post the
next page? Whereas with continuations there is nothing in the database that
I can see and the new page is the continuation, as in (generate-page (+ n
1))?

I have a mixture of both (for no good reason that I couldn't figure out how
to do some parts with continuations after starting with them, due to
wanting to learn how to use them), but realized that if I hit an error and
have to restart the server, all existing users are going to see 'Page
expired' links, which isn't Very Good (TM) even by my standards - or
especially, since I usually do hit bugs that I have to fix after going live.

Is there somewhere a good write-up on a comparison of what is nice about
one style vs the other? I am not asking which is better, but examples that
highlight how they are different or lead to different solutions or
different trade-offs?


> As a practical matter, you can start to go stateless just by substituting
> #lang web-server  for  #lang racket ... odds are that most/all of your
> program will remain the same.  The web-server language enables you to do
> things beyond what a stateful Racket server can do, but you don't need to
> worry about cells and stuffers, etc. until / unless you really need them.
>
>
I'll try that and see what happens. Thanks a lot!

> George
>

Marc

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread George Neuner

Hi Marc,

On 10/13/2018 10:42 AM, Marc Kaufmann wrote:

Thanks George and Philip.

George, while I am sure that in some places I allow using 
continuations after a delay, that's not what I meant. What I feel is 
happening (with little evidence, mind you) is that, when I come back 
to my website after 3 days and open the homepage, it creates it on the 
fly with a *new* continuation (generated now), yet when the link gets 
called it gives me this error. I would have thought this continuation 
is new, yet it seems to throw the error I am talking about more often 
when I haven't visited the site in a while. See below for the servlet 
I am using currently, I am not specifying a manager.


Which means you are using the default manager. That would explain an old 
continuation expiring, but not a new one.


When the program is operating normally, are you seeing *different* 
continuation URLs every time you execute the same send/suspend/... 
call?  Or are all the URLs for the same send/suspend/... call 
identical?   IIRC, the default URL generator includes a nonce, but you 
can create your own URLs.



Philip, thanks, I didn't realize that I had made an active choice. I 
am pretty sure I was simply using stateful servlets because the 
send/suspend/dispatch link on "Continue: Web Applications in Racket" 
links to the stateful servlets page, not to the stateless servlets 
page. If this is not best practice, maybe it would be better to link 
it to the send/suspend/dispatch on the stateless server page. You say:


"Stateless servlets avoid this issue by making continuations 
serializable, so they can be saved on the client, in a database, etc."


Does this mean I have to deal with managing them myself?

Practically speaking, since both of you seem to imply that I should 
use stateless servers, how do I do that? I did skim the page on 
stateless servers, but I don't understand who the web server should 
provide interface-version, stuffer, and start to. Do I have to require 
this file in all the *.rkt files that uses send/suspend/dispatch?


It's not really a matter of "best practice" ... stateful vs stateless 
mostly is a non-issue unless you have limited memory or you really need 
web continuations to be available long duration: e.g., hours or days.


I generally use stateful servers myself, because I don't use web 
continuations.  It's not that I don't like them - it's that I don't 
often have a need for them that isn't better served by using a 
database.  I certainly do use continuations in my programming - I just 
don't use web continuations.  I do think that long duration web 
continuations are a questionable design ... there are just too many 
error possibilities in the web environment.  Short-lived continuations?  
Up to a few minutes?  Maybe ... but I'd need a good use case to justify 
them.



As a practical matter, you can start to go stateless just by 
substituting  #lang web-server  for  #lang racket ... odds are that 
most/all of your program will remain the same.  The web-server language 
enables you to do things beyond what a stateful Racket server can do, 
but you don't need to worry about cells and stuffers, etc. until / 
unless you really need them.


George

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread Marc Kaufmann
Thanks George and Philip.

George, while I am sure that in some places I allow using continuations
after a delay, that's not what I meant. What I feel is happening (with
little evidence, mind you) is that, when I come back to my website after 3
days and open the homepage, it creates it on the fly with a *new*
continuation (generated now), yet when the link gets called it gives me
this error. I would have thought this continuation is new, yet it seems to
throw the error I am talking about more often when I haven't visited the
site in a while. See below for the servlet I am using currently, I am not
specifying a manager.

Philip, thanks, I didn't realize that I had made an active choice. I am
pretty sure I was simply using stateful servlets because the
send/suspend/dispatch link on "Continue: Web Applications in Racket" links
to the stateful servlets page, not to the stateless servlets page. If this
is not best practice, maybe it would be better to link it to the
send/suspend/dispatch on the stateless server page. You say:

"Stateless servlets avoid this issue by making continuations serializable,
so they can be saved on the client, in a database, etc."

Does this mean I have to deal with managing them myself?

Practically speaking, since both of you seem to imply that I should use
stateless servers, how do I do that? I did skim the page on stateless
servers, but I don't understand who the web server should provide
interface-version, stuffer, and start to. Do I have to require this file in
all the *.rkt files that uses send/suspend/dispatch?

#lang

 web-server 
(require

 web-server/http)
(provide

 interface-version

 stuffer

 start

)
(define

 interface-version

 'stateless)
(define

 stuffer

  (stuffer-chain

   serialize-stuffer

   (md5-stuffer

 (build-path

 (find-system-path

 'home-dir) ".urls"
(define

 (start

 req)
  (response/xexpr

   `(html (body (h2 "Look ma, no state!")

Right now, the following is my servlet.rkt file that I start via racket
servlet.rkt:

#lang racket

(require web-server/servlet
 web-server/servlet-env
 db
 racket/date
 web-server/configuration/responders
 web-server/formlets
 "pages.rkt"
 )

;;; Much ado about nothing
...

(serve/servlet start
   #:log-file (build-path (string-append "logs/" date-string
"server.logs"))
   #:servlet-path "/"
   #:servlet-regexp #rx""
   #:launch-browser? #f
   #:extra-files-paths (list (build-path "htdocs"))
   #:servlet-responder my-error-responder)

Thanks 

Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread Philip McGrath
You should only be seeing this issue if you are using stateful servlets, as
opposed to stateless, RESTful servlets in `#lang web-server`. The first
question is whether you really need to be doing that—other than as an
experiment, I never have.

Stateful servlets work by keeping continuation values live in memory.
Keeping all continuations in memory indefinitely will presumably exhaust
your available memory eventually (unless you know you have a short-running
servlet with limited access), but in general there isn't a sound way to
decide when to free them: this is explained more in the papers. Stateful
servlets have *managers* (
http://docs.racket-lang.org/web-server/servlet.html#%28part._managers%29)
that decide when to free saved continuations, typically using a timeout or
least-recently-used policy. The error you are reporting is from visiting a
page that has been freed. So, you probably need to adjust the limits being
given to your servlet's manager, rather than using the default from
`serve/servlet` or equivalent.

Stateless servlets avoid this issue by making continuations serializable,
so they can be saved on the client, in a database, etc.

-Philip


On Sat, Oct 13, 2018 at 9:27 AM Marc Kaufmann 
wrote:

> Hi all,
>
> I am running the Racket web server with continuations and I keep getting
> "Sorry, this page has expired. Please go back." rather sporadically. I
> can't seem to figure out why and when this happens. I get it more on my
> local server running on localhost.
>
> A few patterns that I believe are true (without having rigorously tested
> it):
>
> - When I don't visit my live server for a while (and hence noone does), I
> usually get the error immediately and then when I go back and try again it
> works. Is it possible that it is an issue of something (the continuation
> URL) not being loaded quickly or having to be generated on the fly? Would a
> database connection that has expired lead to this? I remember having issues
> with my database connections going stale (or whatever I'm supposed to call
> that).
> - When I refresh a page, I often get it too (although sometimes that fixes
> the problem?)
>
> This is not a crippling issue, but my guess is that I am doing something
> wrong in how I set up things and eventually I should deal with this.
>
> Cheers,
> Marc
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread George Neuner


On 10/13/2018 9:27 AM, Marc Kaufmann wrote:

Hi all,

I am running the Racket web server with continuations and I keep 
getting "Sorry, this page has expired. Please go back." rather 
sporadically. I can't seem to figure out why and when this happens. I 
get it more on my local server running on localhost.


A few patterns that I believe are true (without having rigorously 
tested it):


- When I don't visit my live server for a while (and hence noone 
does), I usually get the error immediately and then when I go back and 
try again it works. Is it possible that it is an issue of something 
(the continuation URL) not being loaded quickly or having to be 
generated on the fly? Would a database connection that has expired 
lead to this? I remember having issues with my database connections 
going stale (or whatever I'm supposed to call that).
- When I refresh a page, I often get it too (although sometimes that 
fixes the problem?)


This is not a crippling issue, but my guess is that I am doing 
something wrong in how I set up things and eventually I should deal 
with this.


Cheers,
Marc


I would question a design that allows invoking continuations after very 
long delays.  It certainly is possible, e.g., using a stateless server 
(#lang web-server), or by saving state in your database ... but I still 
wouldn't do it.  E.g., I have a search engine app that caches results 
for a time in an unlogged database table, but I don't use web 
continuations to page through them: the initial search specifies the 
requested result "page" size, and a separate retrieval URL requires the 
search id and page #.


AFAIK, a closed DB connection won't cause the error you see ... it will 
do other bad things .  You can use virtual connections [if your 
SQL doesn't rely on prepared statements] to get around the problem, or 
[as I do] use some variety of (with-db-connection ...) macro to get a 
new (pool?) connection whenever you need it.



Did you use  serve-servlet  to start your server running?  If so, did 
you specify a particular continuation manager in the call?  The default 
manager will time out cached continuations after ~4 hours.


see:

   
https://docs.racket-lang.org/web-server/run.html?q=serve-servlet#%28def._%28%28lib._web-server%2Fservlet-env..rkt%29._serve%2Fservlet%29%29
   
https://docs.racket-lang.org/web-server/servlet.html?q=serve-servlet#%28def._%28%28lib._web-server%2Fmanagers%2Flru..rkt%29._make-threshold-.L.R.U-manager%29%29


George

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Web server hits "Sorry, this page has expired. Please go back."

2018-10-13 Thread Marc Kaufmann
Hi all,

I am running the Racket web server with continuations and I keep getting 
"Sorry, this page has expired. Please go back." rather sporadically. I 
can't seem to figure out why and when this happens. I get it more on my 
local server running on localhost.

A few patterns that I believe are true (without having rigorously tested 
it):

- When I don't visit my live server for a while (and hence noone does), I 
usually get the error immediately and then when I go back and try again it 
works. Is it possible that it is an issue of something (the continuation 
URL) not being loaded quickly or having to be generated on the fly? Would a 
database connection that has expired lead to this? I remember having issues 
with my database connections going stale (or whatever I'm supposed to call 
that).
- When I refresh a page, I often get it too (although sometimes that fixes 
the problem?)

This is not a crippling issue, but my guess is that I am doing something 
wrong in how I set up things and eventually I should deal with this.

Cheers,
Marc

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.