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

Tokio reliance #80

Open
stevefan1999-personal opened this issue Sep 18, 2024 · 1 comment
Open

Tokio reliance #80

stevefan1999-personal opened this issue Sep 18, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@stevefan1999-personal
Copy link

At the moment, these are the only few things that indicates Tokio requirement

use tokio::{
sync::Mutex as AsyncMutex,
task::{spawn, JoinHandle},
};

While AsyncMutex should be able to be replaced with https://docs.rs/async-mutex/latest/async_mutex/index.html, for the task runner and async drop it would be a little more tricky.

For task runner, we need to inverse the runtime control back to the user, so the user now has to implement a trait which will supply the async future to a user specific runtime spawner.

And for the async drop, we need to wait for https://rust-lang.github.io/async-fundamentals-initiative/roadmap/async_drop.html.

@stevefan1999-personal
Copy link
Author

I'm able to confirm that this code would allow SurrealKV to run on smol without extra compatibility shim after merging the two PRs!

use std::{env, sync::Arc};

use derive_more::derive::{Display, Error, From};
use surrealkv::{IsolationLevel, Options, Store};

use std::{
    future::Future,
    pin::{pin, Pin},
    result::Result,
    task::{Context, Poll},
};

use surrealkv::async_runtime::{JoinHandle, TaskSpawner};

#[derive(Debug, Display, Error, From)]
enum Error {
    SurrealKv(surrealkv::Error),
    Utf8(std::string::FromUtf8Error),
    ParseInt(std::num::ParseIntError),
    Io(std::io::Error),
}

fn main() -> Result<(), Error> {
    smol::block_on(async {
        let store = Store::with_spawner(
            Options {
                dir: env::current_dir()?.join("./foo"),
                isolation_level: IsolationLevel::SerializableSnapshotIsolation,
                ..Options::default()
            },
            Arc::new(SmolSpawner),
        )?;
        let mut tx = store.begin()?;
        if let Some(foo) = tx.get(b"foo")? {
            let foo = String::from_utf8(foo)?;
            println!("old value {}", foo);
            let mut foo: u32 = foo.parse()?;
            foo += 1;
            println!("new value {}", foo);
            tx.set(b"foo", foo.to_string().as_bytes())?;
        } else {
            tx.set(b"foo", b"1")?;
        }

        tx.commit().await?;
        Ok(())
    })
}

#[derive(Copy, Clone, Default)]
pub struct SmolSpawner;

impl TaskSpawner for SmolSpawner {
    fn spawn<F>(&self, f: F) -> Box<dyn JoinHandle<F::Output> + Unpin>
    where
        F: Future + Send + 'static,
        F::Output: Send + 'static,
    {
        Box::new(SmolJoinHandle(smol::spawn(f).fallible()))
    }
}

pub struct SmolJoinHandle<T>(async_task::FallibleTask<T>);

impl<T> Future for SmolJoinHandle<T> {
    type Output = Result<T, Box<dyn std::error::Error>>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        match pin!(&mut self.0).poll(cx) {
            Poll::Ready(Some(res)) => Poll::Ready(Ok(res)),
            Poll::Ready(None) => Poll::Ready(Err("Task failed".into())),
            Poll::Pending => Poll::Pending,
        }
    }
}

impl<T: Send> JoinHandle<T> for SmolJoinHandle<T> {}

@arriqaaq arriqaaq added the enhancement New feature or request label Oct 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants