redstone-dart / redstone

A metadata driven microframework for Dart.
http://redstone-dart.github.io/redstone
MIT License
342 stars 42 forks source link

Premature closure of a request with multiple futures #54

Closed mkhan-akhan closed 9 years ago

mkhan-akhan commented 9 years ago

Consider the following Future: Future<List> searchWord(String searchText) { var completer = new Completer(); var sql = "select * from words where decorated like " + "'" + searchText + "%' order by decorated";

connect(uri).then((conn){
  List<WordDto> words = new List<WordDto>();
  conn.query(sql).toList()
  .then((rows) {

    for(var row in rows){
      var word = new WordDto.create(row.pk.toString(), row.decorated, row.undecorated);
      words.add(word);
    }

  })
  .whenComplete(() {
    conn.close();
    completer.complete(words);
  });
});

return completer.future;

}

As soon as the connect(uri) future completes the request is closed. The framework does not seem to wait for the topmost future to complete before writing the response for target and then closing the request. Is there any way of getting around this. Thanks.

luizmineo commented 9 years ago

The response is written when the returned Future completes. My guess is that your code is throwing an exception, which makes the whenComplete callback be invoked without the result from the query. To verify if that is the case, you can add a catchError callback. Example:

Future searchWord(String searchText) {
  var completer = new Completer();
  var sql = "select * from words where decorated like " +
  "'" + searchText + "%' order by decorated";

  connect(uri).then((conn){
    List<WordDto> words = new List<WordDto>();
    conn.query(sql).toList()
    .then((rows) {

      for(var row in rows){
        var word = new WordDto.create(row.pk.toString(), row.decorated, row.undecorated);
        words.add(word);
      }

    })
    .catchError((e) {
      print(e);
    })
    .whenComplete(() {
      conn.close();
      completer.complete(words);
    });
  });

  return completer.future;
}
mkhan-akhan commented 9 years ago

I added the catchError callback but the code does not execute through there. I have attached three snapshots of the code execution with the log messages to demonstrate when the request is closed. request_closure_01 request_closure_02 request_closure_03

On 8 December 2014 at 00:53, Luiz Henrique Farcic Mineo < notifications@github.com> wrote:

The response is written when the returned Future completes. My guess is that your code is throwing an exception, which makes the whenComplete callback be invoked without the result from the query. To verify if that is the case, you can add a catchError callback. Example:

Future searchWord(String searchText) { var completer = new Completer(); var sql = "select * from words where decorated like " + "'" + searchText + "%' order by decorated";

connect(uri).then((conn){ List words = new List(); conn.query(sql).toList() .then((rows) {

  for(var row in rows){
    var word = new WordDto.create(row.pk.toString(), row.decorated, row.undecorated);
    words.add(word);
  }

})
.catchError((e) {
  print(e);
})
.whenComplete(() {
  conn.close();
  completer.complete(words);
});

});

return completer.future; }

— Reply to this email directly or view it on GitHub https://github.com/luizmineo/redstone.dart/issues/54#issuecomment-65934896 .

Mohammed Aiyub Khan Auckland, New Zealand

luizmineo commented 9 years ago

I'm not sure if I understood the problem. This searchWord() is annotated with @Route, or it is called by another function that has the @Route annotation? If it is invoked by another function, can you share it too?

Also, if you tried to send me the log messages, I did not receive it. Can you share it through gist?

mkhan-akhan commented 9 years ago

The attachments did not go through when sending through direct email reply. I have updated my last comment by uploading the images through GitHub.

On 8 December 2014 at 09:36, Luiz Henrique Farcic Mineo < notifications@github.com> wrote:

I'm not sure if I understood the problem. This searchWord() is annotated with @Route, or it is called by another function that has the @Route annotation? If it is invoked by another function, can you share it too?

Also, if you tried to send me the log messages, I did not receive it. Can you share it through gist https://gist.github.com/?

— Reply to this email directly or view it on GitHub https://github.com/luizmineo/redstone.dart/issues/54#issuecomment-65953752 .

Mohammed Aiyub Khan Auckland, New Zealand

mkhan-akhan commented 9 years ago

Here is the annotated function that calls searchWord():

@app.Route(urls.searchWordUrl) searchWord(@app.QueryParam() String searchText) {

wordDao.searchWord(searchText).then((words){ var list = new List();

for(var word in words){
  list.add(word.toJsonString());
}

return list;

});
}

luizmineo commented 9 years ago

Thanks! Can you try to change your service function to the following?

@app.Route(urls.searchWordUrl)
searchWord(@app.QueryParam() String searchText) {

  return wordDao.searchWord(searchText).then((words){
    var list = new List();

    for(var word in words){
      list.add(word.toJsonString());
    }

    return list;
  });

}

Note that I've added a return statement to it, so the framework can access the Future object produced by the WordDao.searchWord() method.

Let me know if that helps.

mkhan-akhan commented 9 years ago

Yes! That did it. Many thanks. Much appreciated.