4 ms·
One of the Racket tutorials actually goes into an example of using continuations to save application state for a web app (https://docs.racket-lang.org/more/inde
by slaymaker1907 7y ago
One of the Racket tutorials actually goes into an example of using continuations to save application state for a web app (https://docs.racket-lang.org/more/index.html#%28part._.Continuations%29 https://docs.racket-lang.org/more/index.html#%28part._.Conti...).
One issue with this approach is that it doesn't really scale easily beyond a single server. You need something like the JVM which allows for closures to be sent between machines sharing the same code base. Plus, even in the JVM case, you must have the class files required by the closure available on the JVM which tries to run it.
I really think it is a better idea to just use a database and pass state explicitly rather than trying to do something fancy with continuations. However, continuations can be extremely useful for making the server asynchronous without making it look asynchronous.
While Promises are nice, I think they are severely flawed in that they must "infect" any code which tries to use them. For instance, I was dealing with some Typescript compiler interfaces a few years back which expected to be able to read files synchronously, something which does not hold true if you try to emulate a filesystem in the browser using web requests. With true continuations, it would be possible to simply pause this computation transparently and then resume it once the request was complete.
- gwright 7y agoI don't think you need to pass closures between machines but you do need to use "sticky sessions" so that your load balancers deliver all requests for a particular session back to the same app instance. I haven't seen much discussion of sticky sessions in quite a while as 12-factor apps built around stateless processes have no need for them and that has been the dominant paradigm for quite a while.
- muxator 7y agoAn application requiring sticky session sounds like an architecture smell to me. It works, and you can get a long way with it, but a system that relies on requests always being served by the same server sounds a bad idea to me. What if that server breaks/need a security update/has to be rebooted? For security updates & restarts you can always use session draining, but then your operativity becomes dependent on an upstream service (a LB?), which in a large organization is probably handled by another team, and you end up needing to coordinate and complicate something that could have been simple. As long as it's a conscious choice, it's ok not baking in tolerance for these failure modes, but personally I would only accept it for POCs/prototypes.
- deckard1 7y agoYeah, I don't see how this type of architecture pays off in the end. You're opening yourself up to long-running continuations that provide a DoS memory attack vector, put pressure on the GC, and you still have to figure out when to actually GC. Imagine a shopping cart continuation hanging out for days or even weeks, waiting on the user to click the order button. Now imagine thousands of these. And for what? Just so you can run some logic on the server? Which you really shouldn't be doing in the first place. And who is the lucky person that has to deal with server affinity? Seems like the developer is just tossing his work over the fence to some poor dev ops guy to clean up.
- soegaard 7y agoThese are serious concerns. An attempt to make web programming with continuations work without requiring sticky sessions is "Stateless Servlets": https://docs.racket-lang.org/web-server/stateless.html?q=stateless#%28part._considerations%29 https://docs.racket-lang.org/web-server/stateless.html?q=sta... A stateless servlets makes it possible to serialize continuations and store them on the client/database/disk. There is no such thing as a free lunch, so that approach has pros and cons too.
- namelosw 7y agoIt seems passing closure is not quite scalable since any closure could be accidentally extremely huge. I found for distribute environment, the big idea is still messaging.
- WallWextra 7y agoThe racket web framework has an option to serialize the entire continuation for he client to send back to you. Pretty intense.
- brandmeyer 7y agoActually, Racket does have serializable closures. https://docs.racket-lang.org/web-server-internal/closure.html https://docs.racket-lang.org/web-server-internal/closure.htm... I prefer to explicitly serialize state, because its easier to reason about. Its harder to assert that request A was definitely using/not-using some bit of state that request B was using when you are automatically serializing a bunch of lexical variables in the background. This is just the bias of my personal experience though, I'm a pretty low-level guy.
- heavenlyblue 7y agoSpeaking of serializable closures: does anyone here know of any work being done on languages that would support nameable, completely size-transparent and versionable closures across different code versions? This isn’t something out of the ordinary, you would think - but I can easily see how that could be hard to implement.