Skip to content

Instantly share code, notes, and snippets.

@fisherdarling
Created November 15, 2022 08:31
Show Gist options
  • Save fisherdarling/f78a55f58cb7fc4167c16bee04744001 to your computer and use it in GitHub Desktop.
Save fisherdarling/f78a55f58cb7fc4167c16bee04744001 to your computer and use it in GitHub Desktop.
DO Inserter Implementation with Usage
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use worker::*;
use workers_do_proxy::{
durable_object_proxy,
error::Error,
proxy::{ProxiedObject, ProxiedRequest},
Ctx,
};
use workers_traits::{env::Env, state::State, storage::Storage};
type Result<T, E> = std::result::Result<T, E>;
pub struct Inserter;
#[derive(Debug, Serialize, Deserialize)]
pub enum InserterRequest {
Insert {
key: String,
value: serde_json::Value,
},
Get {
key: String,
},
Delete {
key: String,
},
}
#[async_trait(?Send)]
impl<S: State, E: Env> ProxiedObject<S, E> for Inserter {
const BINDING: &'static str = "INSERTER_OBJECT";
type Init = ();
type Request = InserterRequest;
type Response = Option<serde_json::Value>;
// Called when the object is first created (before `load`).
async fn init(ctx: Ctx<'_, S, E>, init: Self::Init) -> Result<Self, Error> {
Ok(Inserter {})
}
// Called on each request to the object.
async fn load(ctx: Ctx<'_, S, E>) -> Result<Self, Error> {
Ok(Inserter {})
}
async fn fetch(
&mut self,
ctx: Ctx<'_, S, E>,
req: ProxiedRequest<InserterRequest>,
) -> Result<Option<serde_json::Value>, Error> {
match req {
ProxiedRequest::Request(InserterRequest::Insert { key, value }) => {
ctx.state.storage().put(&key, value).await?;
Ok(None)
}
ProxiedRequest::Request(InserterRequest::Get { key }) => {
Ok(Some(ctx.state.storage().get(&key).await?))
}
ProxiedRequest::Request(InserterRequest::Delete { key }) => {
ctx.state.storage().delete(&key).await?;
Ok(None)
}
ProxiedRequest::Alarm => {
unimplemented!()
}
}
}
}
durable_object_proxy!(Inserter, InserterObject);
pub mod inserter;
use inserter::{Inserter, InserterRequest};
use serde_json::json;
use worker::*;
use workers_do_proxy::stub_ext::EnvExt;
#[worker::event(fetch, respond_with_errors)]
pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> Result<Response> {
let obj = env.obj::<Inserter>("test")?;
obj.send(InserterRequest::Insert {
key: "some_id".to_string(),
value: json!({ "hello": "world!" }),
})
.await?;
let value = obj
.send(InserterRequest::Get {
key: "some_id".to_string(),
})
.await?
.unwrap();
Response::from_json(&value)
}
@fisherdarling
Copy link
Author

Decided dynamic dispatch was better than generic params, it's now just:

impl ProxiedObject for Inserter {
    const BINDING: &'static str = "INSERTER_OBJECT";

    type Init = ();
    type Request = InserterRequest;
    type Response = Option<serde_json::Value>;

    // Called when the object is first created (before `load`).
    async fn init(ctx: Ctx<'_>, init: Self::Init) -> Result<Self, Error> {
        Ok(Inserter {})
    }

    ....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment