Hi,
I'm playing and digging in flow-enabled petstore (BTW, so nice, I love it), and experienced some problems with the continutation-enabled prev/next navigation.
To reproduce it, go to the "dogs" area, click "next" once and then hit the browser's reload button. The prev and next links are now totally screwed.
Any ideas on what's going on ?
Yep. It's a bug. Here's a fix:
function viewCategory() {
var categoryId = cocoon.request.get("categoryId");
var category = getPetStore().getCategory(categoryId);
var skipResults = 0;
var maxResults = MAX_RESULTS;
while (true) {
var productList = getPetStore().getProductListByCategory(categoryId,
skipResults,
maxResults); sendPageAndWait("/view/Category.html", { accountForm: accountForm, productList: productList.rows, category: category, firstPage: skipResults == 0, lastPage: !productList.isLimitedByMaxRows }); var page = cocoon.request.get("page"); if (page == "previous") { if (skipResults != 0) { skipResults -= maxResults; } } else if (page == "next") { if (!productList.isLimitedByMaxRows) { skipResults += productList.rowCount; } } } }
Moreover, AFAIU, the "productList" variable in viewCategory() is stored in the continuation, and so if we hit "next" and then "prev", the first list exists twice (in different continuations). Isn't there a potential memory consumption problem ? I know continuations expire, but withing the expiration delay, all these lists keep floating around...
Yes, but the only things that are really duplicated are the program counter and stack frames, and even the stack itself is lazily copied. The local variables themselves (like productList) are shared between continuations.
That being said, it is still possible to explicitly free memory when a continuation is captured, using this extended JavaScript syntax:
catch (break) { // the continuation I'm part of is about to be captured // code to handle that goes here }
catch (continue) { // the continuation I'm part of is about to be resumed // code to handle that goes here }
For example you could get rid of productList like this:
function viewCategory() {
var categoryId = cocoon.request.get("categoryId");
var category = getPetStore().getCategory(categoryId);
var skipResults = 0;
var maxResults = MAX_RESULTS;
while (true) {
var productList = getPetStore().getProductListByCategory(categoryId,
skipResults,
maxResults); var lastPage = !productList.isLimitedByMaxRows; var rowCount = productList.rowCount; sendPageAndWait("/view/Category.html", { accountForm: accountForm, productList: productList.rows, category: category, firstPage: skipResults == 0, lastPage: lastPage }); catch (break) { // zap product list before returning // page to browser print("zapping productList"); productList = null; } catch (continue) { print("return from continuation"); print("productList = " + productList); } var page = cocoon.request.get("page"); if (page == "previous") { if (skipResults != 0) { skipResults -= maxResults; } } else if (page == "next") { if (!lastPage) { skipResults += rowCount; } } } }