Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The way your routes work mean that a response is expected to be immediately generated and returned. It would be much nicer if a response object was passed to the callback and you could return immediately from the callback, but send a response independently, when you are ready. Kind of like this:

  CROW_ROUTE(app, "/about")
    ([](Response res){
        res.send("About Crow example");
    });
Why you might ask? So you can do this:

  CROW_ROUTE(app, "/about")
    ([](Response res){
        responses.push_back(res);
    });
And then some independent method could come along and do the res.send() when it is ready. The connection would hang until res.send() or similar is called on it. There would also be methods on the Response object so you can see if the connection is still alive etc, and maybe the ability to set timeouts directly on the Response object.

[edit] This would allow people using your framework to implement long polling without locking up an io_service thread for each connection. It would also make it easier to add support for web sockets etc at a later date.

[edit2] This is how NodeJS works. Both a request and a response object is passed to the callback, then you can do for example:

  function callback (req, res) {
      setTimeout(function(){
          res.writeHead(200, {'Content-Type': 'text/plain'});
          res.end('Hello World\n');
      }, 5000);
  }


I agree that allowing implementing long polling with crow is important, just I didn't know a good way to do that. Your suggestion is big help.

I think supporting both way is better if there is a enough explanation. I don't want to drop a simpler way to do the same job.

  CROW_ROUTE(app, "/about")
    ([](){
        return "About Crow example";
    });

  CROW_ROUTE(app, "/about")
    ([](Response res){
        res.send("About Crow example");
    });


^this is exactly how twisted implements their web resources.


If all of this is happening in it's own thread (and there's probably 1 thread per connection), why add the overhead and complexity of something like this?


I've looked at his code and that is not how it works. It uses boost::asio. You specify how many io_service threads to run. It is not 1 thread per connection. You could easily have 10000 connections spread across 4 threads for example. The threads that handle the connections are the same threads which run the callbacks. You wouldn't want threads being blocked by callbacks that take a long time to run. You'd want to pass those operations off to a different thread pool. So you would want to be able to do what I have suggested.

Also, you said this adds complexity and overhead. I dispute that it adds complexity. For most people: "return stuff" vs "res.send(stuff)". And I wouldn't assume that it would add any overhead either. If you disagree, let me know when you've read the code and understand how boost::asio works.


It's important to note that requiring 10000+ real threads would be a huge limitation, performance-wise. At that scale you end up with a lot of overhead from process switching.

The difference is a big reason why Apache 2.2 would slow to a crawl and eat up gigabytes of RAM at 100% processor utilization on the same load that Nginx could handle with 10Mb of RAM and 20% processor utilization. [1] (I understand more recent versions of Apache now support polling [2].)

[1] See, for example, this explanation: http://stackoverflow.com/questions/2583350/is-epoll-the-esse...

[2] https://httpd.apache.org/docs/2.4/mod/event.html


Seems like you could do something much cleaner by simply using Boost.Coroutine or some such...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: