use anyhow::Error;
use thingvellir::{service_builder, DataLoadRequest, LoadFromUpstream, ServiceData};

#[derive(Clone, Default)]
struct MaybeExists {}

impl<Data: ServiceData + Default> LoadFromUpstream<u64, Option<Data>> for MaybeExists {
    fn load(&mut self, request: DataLoadRequest<u64, Option<Data>>) {
        if *request.key() == 1 {
            println!("loading {} found", request.key());
            request.resolve(Some(Default::default()));
        } else {
            println!("loading {} not found", request.key());
            request.resolve(None);
        }
    }
}

#[derive(Default, Clone)]
struct Counter;

impl ServiceData for Counter {}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let (mut service, _shutdown) =
        service_builder::<u64, Option<Counter>>(1000).build(MaybeExists {});

    assert!(service.execute(1, |x| x.is_some()).await?);
    assert!(!(service.execute(2, |x| x.is_some()).await?));

    // We drop the shutdown handle here at the same time as the tokio runtime is shutting down.
    // So, the shutdown will rarely (if at all) complete gracefully.
    // To properly shutdown, it's best to invoke ShutdownHandle::spawn_graceful_shutdown() and
    // GracefulShutdownHandle::get_shutdown_result().await to wait for the shutdown to complete.

    Ok(())
}
