Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: streaming functions #190

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft

Feat: streaming functions #190

wants to merge 2 commits into from

Conversation

JonasKruckenberg
Copy link
Contributor

@JonasKruckenberg JonasKruckenberg commented Sep 10, 2023

This adds the initial implementation of streaming responses of functions aka the stream pseudo-type.

It's a pseudo to type because while it looks like any regular type: stream<t> the only valid position where it may appear is as the sole return type of a function like so

interface streams {
   func streaming_bytes() -> stream<list<u8>>
}

(This restriction might be gradually lifted at some point)

The primary motivation for this new addition is to model sequences of asynchronously produced data such as events, log streams, or just streaming bytes from e.g. the disk.
With this addition the tauri-bindgen system can finally replace the current IPC system as this allows us to model events (in an IMO type-safer and more ergonomically way)

Details

The generated guest rust code look like this:

pub async fn streaming_bytes() -> ::tauri_bindgen_guest_rust::Streaming<Vec<u8>>;

where ::tauri_bindgen_guest_rust::Streaming<T> takes care of the underlying raw http stream and deserialisation of the incoming data. It in turn implements Stream<Item = T>.
It's worth noting that currently the implementation relies on ReadableStreams returned by fetch, and so performs no additional buffering (everything follows the rust pull-based model here which is nice).

Streaming<T> doesn't implement framing yet though it probably should.

The generated host code looks like this:

pub trait Streams: Sized {
    type StreamingBytesStream: ::tauri_bindgen_host::Stream<Item = Vec<u8>>
        + Send
        + 'static;
    ///A function that returns a stream of strings
    fn streaming_bytes(&self) -> Self::StreamingBytesStream;
}

So an implementation would need to give a specific type for StreamingBytesStream (most likely some wrapper type)

struct Ctx {
   // a list of handles so we can send events to all open channels
   // this emulates a broadcast channel
   txs: Arc<Mutex<Vec<mpsc::Sender<Bytes>>>>
}


impl Streams for Ctx {
   type StreamingBytesStream = tokio_stream::wrappers::ReceiverStream<Bytes>;

   fn streaming_bytes(&self) -> Self::StreamingBytesStream {
      let (tx, rx) = mpsc::channel(250);

      // this can of course be refactored to not require locking
      let txs = self.txs.lock().unwrap();
      txs.push(tx);

      Self::StreamingBytesStream::new(rx)
   }
}

The above example also showcases how a similar DX to the classical tauri events can be achieved, by essentially passing around mpsc::Sender handles.

Note

This PR is currently blocked by the fact that wry's event handler doesn't allow for streaming responses back to the webview tauri-apps/wry#1022

TODO list

  • Host implementation
  • Guest JS implementation
  • Guest TS implementation
  • Guest Rust implementation
  • Markdown implementation

This closes #180

@netlify
Copy link

netlify bot commented Sep 10, 2023

Deploy Preview for tauri-bindgen ready!

Name Link
🔨 Latest commit 4731e0b
🔍 Latest deploy log https://app.netlify.com/sites/tauri-bindgen/deploys/64fe1750416be600081fc4fc
😎 Deploy Preview https://deploy-preview-190--tauri-bindgen.netlify.app/
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@jquesada2016
Copy link

I love this!

Since stream can only appear in the output of the function, how is the guest supposed to mimic the event emitter pattern the host has?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Any plans to expand the scope to the tauri event system?
2 participants