What an object's storage can do that workers-rs has no binding for: go back to an earlier moment, and do several statements as one.
Cloudflare keeps thirty days of an SQLite object's history. A moment in it is named by a bookmark; told to restore to one, the object has that moment's storage the next time it starts. That rewinds everything the object keeps: it is for a migration that went wrong minutes ago, not for taking back one row.
The object's state as the runtime gave it, for the calls below.
28impl Past {
Takes a second hold on state, and gives it back.
Calls storage.<name>(argument).
37 fn storage(&self, name: &str, argument: &JsValue) -> Result<JsValue, String> { 38 let storage = Reflect::get(&self.0, &"storage".into()).map_err(message)?; 39 let method: Function = Reflect::get(&storage, &name.into()).map_err(message)?.dyn_into().map_err(|_| format!("the storage has no {name}"))?; 40 method.call1(&storage, argument).map_err(message) 41 }
43 async fn text(&self, name: &str, argument: &JsValue) -> Result<String, String> { 44 let promise: Promise = self.storage(name, argument)?.dyn_into().map_err(|_| format!("{name} did not return a promise"))?; 45 JsFuture::from(promise).await.map_err(message)?.as_string().ok_or_else(|| format!("{name} did not answer with a bookmark")) 46 }
The bookmark for at_ms, which must be in the last thirty days, or
for now. Asking changes nothing.
Has the object's storage be as it was at bookmark when it next
starts, and answers with the bookmark of the moment before that, to
undo it by. restart is what makes it happen.
Ends the object where it stands; the next request starts it again. Whatever is waiting on it fails.
Runs all as one: if it fails, nothing it wrote is kept.
73 pub fn atomically(&self, all: impl FnOnce() -> worker::Result<()> + 'static) -> Result<(), String> { 74 let failed = std::rc::Rc::new(std::cell::RefCell::new(None)); 75 let said = failed.clone(); 76 // A callback that throws is what rolls the transaction back. 77 let callback = Closure::once_into_js(move || -> Result<JsValue, JsValue> { 78 all().map(|()| JsValue::UNDEFINED).map_err(|error| { 79 let error = error.to_string(); 80 *said.borrow_mut() = Some(error.clone()); 81 JsValue::from(js_sys::Error::new(&error)) 82 }) 83 }); 84 let done = self.storage("transactionSync", &callback).map(|_| ()); 85 match failed.borrow_mut().take() { 86 Some(error) => Err(error), 87 None => done, 88 } 89 } 90}