3

It just occurred to me that it would make sense to stream strings, each representing an element from a database query instead of returning the whole list of them at the end of the process, this might get the first result earlier on the browser. So I tried to implement this with Redstone which uses Shelf. Here is my basic test

@app.Route ('/testStream')
testSream ()
{
    StreamController<String> controller = new StreamController<String> ();

    () async
    {
        var initialTime = new DateTime.now();

        await new Future.delayed (new Duration (seconds: 1));
        controller.add("hello\n");

        await new Future.delayed (new Duration (seconds: 10));
        controller.add("chao\n");

        var finalTime = new DateTime.now().difference(initialTime);

        controller.add(finalTime.toString());

        controller.close();

    }();

    Stream<List<int>> intStream = controller.stream.map((s) => s.codeUnits);

    return new shelf.Response.ok (intStream);
}

Just for some context, the Linked-in guys use "text streaming" in a pattern they got from Facebook to render parts of the page quickly and insert some latter (as its available), they implement this in Playframework (Scala) where they use Enumerables which seem behave just like Dart streams. You can see it in this video.

The problem with my code is that while I expected it to show "hello" after 1 second, and "chao" 10 seconds later. What I get is 11 seconds of waiting and then the complete text. As you see, I am responding a Shelf.Response with a Stream<List<int>> where each List<int> is just a the string from the original stream converted into bytes.

Is this a Shelf problem/feature, or is Redstone messing around with the response and converting it to a future? Is there any work around?

EDIT

What I want to get

Nothing for 1 second.

After 1 second

hello

After 11 seconds

hello
chao
0:00:11.009000

What I really get

Nothing for 1 second.

After 11 seconds

hello
chao
0:00:11.009000
Cristian Garcia
  • 9,630
  • 6
  • 54
  • 75
  • Isn't this a similar problem? http://stackoverflow.com/questions/29081144 – Günter Zöchbauer Mar 24 '15 at 18:30
  • @GünterZöchbauer not quite. My problem is that the browser doesn't receive ANY data util the stream closes. I want it to receive data any time the stream gets data. – Cristian Garcia Mar 24 '15 at 19:23
  • Can this work with HTTP? If you use WebSocket you get this for free. – Günter Zöchbauer Mar 24 '15 at 19:26
  • Don't think so, I don't need bidirectional communication. Also, Linked-in people used it on normal HTTP GET requests to render their page. – Cristian Garcia Mar 24 '15 at 19:34
  • Honestly I don't know. Let's see if other comments provide more insight. – Günter Zöchbauer Mar 24 '15 at 19:46
  • I know in Java they have some Stream HTTP Response thing (from JSR 353), maybe you could check that out. – Pacane Mar 24 '15 at 20:46
  • I'm surprised that doesn't work. I had planned to try something similar at some point. Have you tried adding the interest codes directly to your controller to avoid the map step. Just in case the map is not behaving as you expect – Anders Mar 25 '15 at 21:47
  • @Anders, It was a shelf issue and it has been fixed, but you have to enable this as an option. I really don't use shelf directly and I haven't tried the solution as to give you any advice. – Cristian Garcia Mar 26 '15 at 03:38
  • @Cristian Garcia can you point to a place where it was fixed/changed? – iafonov Dec 15 '15 at 14:47
  • 1
    For those reading this -- https://github.com/dart-lang/shelf/issues/54 – Pacane Apr 14 '16 at 18:46

1 Answers1

0

For those who get here later:

As @Pacane suggested in the question comment, the link (https://github.com/dart-lang/shelf/issues/54) he posted does contain a comment by Andersmholmgren that works for the issue:

return new Response.ok(counterStream, context: {"shelf.io.buffer_output": false}); 

Setting the "shelf.io.buffer_output" option to false disables Shelf's output buffer and make bytes added to response stream directly sent over the network to client.

Zili FENG
  • 191
  • 11