-
Notifications
You must be signed in to change notification settings - Fork 226
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
Viaduct replacement demo #6018
base: main
Are you sure you want to change the base?
Viaduct replacement demo #6018
Conversation
88045a9
to
92d1861
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #6018 +/- ##
=======================================
Coverage ? 22.64%
=======================================
Files ? 330
Lines ? 29814
Branches ? 0
=======================================
Hits ? 6750
Misses ? 23064
Partials ? 0 ☔ View full report in Codecov by Sentry. |
0810d75
to
11a0ba5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Far out, this is fantastic - it's small and simple. I guess seeing what the necko backend looks like is where the fun starts? Either way, I think this is worth pursuing.
components/fairy-bridge/README.md
Outdated
|
||
## Cookies / State | ||
|
||
Cookies are explicitly not supported at the moment, adding them would require a separate security |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know you copy/pasted this, but can we tighten this more? eg, "Cookies and state are outside the scope of this library. Any such functionality is the responsibility of the consumer"
|
||
## Name | ||
|
||
`fairy-bridge` is named after the Fairy Bridge (Xian Ren Qiao) -- the largest known natural bridge in the world, located in northwestern Guangxi Province, China. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
love it :)
pub struct BackendSettings { | ||
// Connection timeout (in ms) | ||
#[uniffi(default = None)] | ||
pub connect_timeout: Option<u32>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, I'm sure you copied these, but I wonder if these are actually appropriate defaults for timeouts? If someone neglects to think about this, it seems better the request times out too soon than never times out? Or maybe make them a non-option - I'm not sure it ever makes sense to say "it's fine if this request literally never completes" - much like we are implicitly also not allowing "it's fine if redirects never complete" below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great point, but we'll need a UniFFI fix for this: mozilla/uniffi-rs#1925
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While that PR makes sense, do we really need that here? ie, can we just make those values u32? I think that would offer ~600 hours of timeout?
(I don't really care, it's more just random thoughts about the API rather than a concrete suggestion)
components/fairy-bridge/src/lib.rs
Outdated
mod error; | ||
pub mod headers; | ||
mod request; | ||
#[cfg(feature = "reqwest")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there doesn't appear to be a feature of this name? (I was going to ask whether it should be, say, "backend-reqwest" or similar, even though it really doesn't matter :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The feature is implicit because of the optional dependency. But "backend-reqwest" sounds better to me too.
components/fairy-bridge/src/lib.rs
Outdated
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
use once_cell::sync::OnceCell; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be now be using std::cell::OnceCell
?
#[derive(uniffi::Record)] | ||
pub struct Request { | ||
pub method: Method, | ||
pub url: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
many of your fns use Url
- should we try and use that here and leverage custom types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes a lot of sense, but I'm slightly worried about conversion errors. If Request.url
is an Url
, then Response.url
maybe also should be. But that means that a request could fail if the foreign code returns an invalid URL. Maybe that's bad? I'm not really sure about this one.
/// this to fail hard with an easy to track down panic, than for e.g. `sync` | ||
/// to fail with a JSON parse error (which we'd probably attribute to | ||
/// corrupt data on the server, or something). | ||
pub fn json<T: ?Sized + serde::Serialize>(mut self, val: &T) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the trait bounds are cool, but I wonder if, for all the reasons you mention in the comment, this should just take serde_json::Value
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried that out, but I felt like it made the consumer code kind of awkward. I do find this docstring a bit weird though. I'm going to update the trait bounds a bit and return a Result. I think it's more natural for consumers to deal with serialization errors than have the function panic.
pub fn json<T: ?Sized + serde::Serialize>(mut self, val: &T) -> Self { | ||
self.body = | ||
Some(serde_json::to_vec(val).expect("Rust component bug: serde_json::to_vec failure")); | ||
if !self.headers.contains_key(headers::CONTENT_TYPE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would seem odd if the existing header had anything but app/json? (Not sure what you should do in that case - if it turns out a use-case for this was legitimate, even logging would be a PITA. OTOH, if there were no valid use-cases, then this would probably result in hard-to-track-down errors which naively might also be attributed to the server instead of the app
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Let's just force the header to be application/json
. json()
is just a convenience method after all, the user can always serialize the data themselves.
pub fn init_reqwest_backend(settings: BackendSettings) -> Result<(), FairyBridgeError> { | ||
// Create a multi-threaded runtime, with 1 worker thread. | ||
// | ||
// The difference between this and the current thread worker, is that it will manage the worker |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what "the current thread worker" is in this context - the current thread is likely to just be a normal thread and not associated with tokio at all, right? (well, tbh I don't really understand this comment at all :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a tokio thing. The runtime always piggybacks on the current thread. You can spawn tasks on the worker, but nothing happens until you call block_on
, which then blocks the current thread while the tasks execute. I thought it would be the right runtime, since we only need one thread, but the execution model is very different. I'll try to update this comment to make it more clear.
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
use std::collections::HashMap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like it might be fine for this to be in lib.rs? (Also fine not to be, I'm just throwing comments out there as they fleetingly enter and leave my brain :)
Thanks for the review! I just updated a bunch of code based on the suggestions. I think you're right that the real interesting part will come from integrating with Necko. If the UniFFI bits are the boring part, I guess that's a good sign. |
8272beb
to
dac259b
Compare
476e13f
to
c003902
Compare
51e7bb6
to
d1d6654
Compare
This shows off a potential viaduct replacement that uses new UniFFI features. Check out `components/fairy-bridge/README.md` and `examples/fairy-bridge-demo/README.md` for details. Execute `examples/fairy-bridge-demo/run-demo.py` to test it out yourself. The UniFFI features are still a WIP. This is currently using a branch in my repo. The current plan for getting these into UniFFI main is: - Get the `0.26.0` release out the door - Merge PR mozilla#1818 into `main` - Merge my `async-trait-interfaces` branch into main (probably using a few smaller PRs) There is a C++ backend using libcurl. I think that necko shouldn't be any harder than this.
This shows off a potential viaduct replacement that uses new UniFFI features.
The 1000ft view is that:
async_trait
crate)Check out the fairy-bridge README and the demo README for details. Execute
run-demo.py
to test it out yourself.The UniFFI features are still a WIP. This is currently using a branch in my repo. The current plan for getting these into UniFFI main is:
0.26.0
release out the doormain
async-trait-interfaces
branch into main (probably using a few smaller PRs)The Desktop plan needs to be explored more. I believe there should be a way to use Necko in Rust code, but that needs to be verified.
I made this using UniFFI proc-macros, to test out the technology and I have to say it was very pleasant to work with.