mpetrunic / fastify-sse-v2

Provide Server-Sent Events to Fastify

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Handle error thrown when an async iterable is used

sinedied opened this issue · comments

When I'm using reply.sse(myAsyncGenerator), if myAsyncGenerator function throws an exception I cannot catch it and gracefully return an error, even if the call is enclosed in a try / catch.

Example:

      try {
          const generator = await getMyAsyncGenerator();
          reply.sse(generator);
        } else {
          return await askApproach.run(question, overrides ?? {});
        }
      } catch (error) {
        // it's never going here
      }

Is there something I'm missing, or should I simply not use this form if I want to catch generator errors?
If I handle the async generator manually, I'm able to catch the error:

      try {
          const generator = await getMyAsyncGenerator();
          for await (const chunk of generator) {
            reply.sse(chunk);  
          }
          reply.sseContext.source.end();
        } else {
          return await askApproach.run(question, overrides ?? {});
        }
      } catch (error) {
        // here I can gracefully handle the error
      }

Thanks

The thing is, I'm converting async iterable to stream which in turn converts errors into error events: https://github.com/alanshaw/it-to-stream/blob/v1.0.0/src/duplex.js#L39
If I exposed that stream you could set event listener to listen for those error events.

Buuuut, what's the point?
Throwing error inside the async generator will kill the loop and end the stream. I would suggest to organise your code to make sure the async iterator you send to see never throws. Instead, it can either yield a message containing an error description or you can pass some event emitter to async generator and emit error events instead of throwing them.

Making my async generator to not throw is not an option for me.
Having the stream ends prematurely on error seems fine to me, but I understand why it would makes things complicated to support it. The second approach I posted works fine as a workaround, so that's hood enough for me even if it's more verbose.

Maybe it would be helpful to add a note in the readme, explaining that if you're using the async generator version, it should not throw?