viaduct/
new_backend.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3*
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6// Right now we're in a transition period where we have 2 backend traits.  The old `Backend`
7// trait is defined in `backend.rs` and the new `Backend` trait is bdefined here
8//
9// The new backend trait has a few of improvements to the old backend trait:
10//   - UniFFI-compatible
11//   - async-based
12//   - Inputs per-request settings for things like timeouts, rather than using global values
13//
14// See `README.md` for details about the transition from the old to new API.
15
16use std::sync::{Arc, OnceLock};
17
18use crate::{
19    backend as old_backend, settings::GLOBAL_SETTINGS, ClientSettings, Request, Response, Result,
20    ViaductError,
21};
22
23#[uniffi::export(with_foreign)]
24#[async_trait::async_trait]
25pub trait Backend: Send + Sync + 'static {
26    async fn send_request(&self, request: Request, settings: ClientSettings) -> Result<Response>;
27}
28
29static REGISTERED_BACKEND: OnceLock<Arc<dyn Backend>> = OnceLock::new();
30
31#[uniffi::export]
32pub fn init_backend(backend: Arc<dyn Backend>) {
33    old_backend::set_backend(Box::leak(Box::new(backend.clone())));
34    if REGISTERED_BACKEND.set(backend).is_err() {
35        error_support::report_error!(
36            "viaduct-multiple-init-backend",
37            "init_backend called multiple times"
38        );
39    }
40}
41
42pub fn get_backend() -> Result<&'static Arc<dyn Backend>> {
43    REGISTERED_BACKEND
44        .get()
45        .ok_or(ViaductError::BackendNotInitialized)
46}
47
48impl old_backend::Backend for Arc<dyn Backend> {
49    fn send(&self, request: crate::Request) -> Result<crate::Response, crate::ViaductError> {
50        let settings = GLOBAL_SETTINGS.read();
51        let client_settings = ClientSettings {
52            timeout: match settings.read_timeout {
53                Some(d) => d.as_millis() as u32,
54                None => 0,
55            },
56            redirect_limit: if settings.follow_redirects { 10 } else { 0 },
57            ..ClientSettings::default()
58        };
59        pollster::block_on(self.send_request(request, client_settings))
60    }
61}