[go: up one dir, main page]

worker/
durable.rs

1//! Durable Objects provide low-latency coordination and consistent storage for the Workers platform.
2//! A given namespace can support essentially unlimited Durable Objects, with each Object having
3//! access to a transactional, key-value storage API.
4//!
5//! Durable Objects consist of two components: a class that defines a template for creating Durable
6//! Objects and a Workers script that instantiates and uses those Durable Objects.
7//!
8//! The class and the Workers script are linked together with a binding.
9//!
10//! [Learn more](https://developers.cloudflare.com/workers/learning/using-durable-objects) about
11//! using Durable Objects.
12
13use std::{fmt::Display, ops::Deref, time::Duration};
14
15use crate::{
16    date::Date,
17    env::{Env, EnvBinding},
18    error::Error,
19    request::Request,
20    response::Response,
21    Result, WebSocket,
22};
23
24use chrono::{DateTime, Utc};
25use futures_util::Future;
26use js_sys::{Map, Number, Object};
27use serde::{de::DeserializeOwned, Serialize};
28use wasm_bindgen::{prelude::*, JsCast};
29use worker_sys::{
30    DurableObject as EdgeDurableObject, DurableObjectId,
31    DurableObjectNamespace as EdgeObjectNamespace, DurableObjectState, DurableObjectStorage,
32    DurableObjectTransaction,
33};
34// use wasm_bindgen_futures::future_to_promise;
35use wasm_bindgen_futures::{future_to_promise, JsFuture};
36
37/// A Durable Object stub is a client object used to send requests to a remote Durable Object.
38#[derive(Debug)]
39pub struct Stub {
40    inner: EdgeDurableObject,
41}
42
43unsafe impl Send for Stub {}
44unsafe impl Sync for Stub {}
45
46impl Stub {
47    /// Send an internal Request to the Durable Object to which the stub points.
48    pub async fn fetch_with_request(&self, req: Request) -> Result<Response> {
49        let promise = self.inner.fetch_with_request(req.inner())?;
50        let response = JsFuture::from(promise).await?;
51        Ok(response.dyn_into::<web_sys::Response>()?.into())
52    }
53
54    /// Construct a Request from a URL to the Durable Object to which the stub points.
55    pub async fn fetch_with_str(&self, url: &str) -> Result<Response> {
56        let promise = self.inner.fetch_with_str(url)?;
57        let response = JsFuture::from(promise).await?;
58        Ok(response.dyn_into::<web_sys::Response>()?.into())
59    }
60
61    pub fn into_rpc<T: JsCast>(self) -> T {
62        self.inner.unchecked_into()
63    }
64}
65
66/// Use an ObjectNamespace to get access to Stubs for communication with a Durable Object instance.
67/// A given namespace can support essentially unlimited Durable Objects, with each Object having
68/// access to a transactional, key-value storage API.
69#[derive(Debug, Clone)]
70pub struct ObjectNamespace {
71    inner: EdgeObjectNamespace,
72}
73
74unsafe impl Send for ObjectNamespace {}
75unsafe impl Sync for ObjectNamespace {}
76
77impl ObjectNamespace {
78    /// This method derives a unique object ID from the given name string. It will always return the
79    /// same ID when given the same name as input.
80    pub fn id_from_name(&self, name: &str) -> Result<ObjectId> {
81        self.inner
82            .id_from_name(name)
83            .map_err(Error::from)
84            .map(|id| ObjectId {
85                inner: id,
86                namespace: Some(self),
87            })
88    }
89
90    /// This method parses an ID that was previously stringified. This is useful in particular with
91    /// IDs created using `unique_id(&self)`, as these IDs need to be stored somewhere, probably as
92    // as a string.
93    ///
94    /// A stringified object ID is a 64-digit hexadecimal number. However, not all 64-digit hex
95    /// numbers are valid IDs. This method will throw if it is passed an ID that was not originally
96    /// created by newUniqueId() or idFromName(). It will also throw if the ID was originally
97    /// created for a different namespace.
98    pub fn id_from_string(&self, hex_id: &str) -> Result<ObjectId> {
99        self.inner
100            .id_from_string(hex_id)
101            .map_err(Error::from)
102            .map(|id| ObjectId {
103                inner: id,
104                namespace: Some(self),
105            })
106    }
107
108    /// Creates a new object ID randomly. This method will never return the same ID twice, and thus
109    /// it is guaranteed that the object does not yet exist and has never existed at the time the
110    /// method returns.
111    pub fn unique_id(&self) -> Result<ObjectId> {
112        self.inner
113            .new_unique_id()
114            .map_err(Error::from)
115            .map(|id| ObjectId {
116                inner: id,
117                namespace: Some(self),
118            })
119    }
120
121    /// Durable Objects can be created so that they only run and store data within a specific
122    /// jurisdiction to comply with local regulations. You must specify the jurisdiction when
123    /// generating the Durable Object's id.
124    ///
125    /// Jurisdiction constraints can only be used with ids created by `unique_id()` and are not
126    /// currently compatible with ids created by `id_from_name()`.
127    ///
128    /// See supported jurisdictions and more documentation at:
129    /// <https://developers.cloudflare.com/durable-objects/reference/data-location/#restrict-durable-objects-to-a-jurisdiction>
130    pub fn unique_id_with_jurisdiction(&self, jd: &str) -> Result<ObjectId> {
131        let options = Object::new();
132        js_sys::Reflect::set(&options, &JsValue::from("jurisdiction"), &jd.into())?;
133        self.inner
134            .new_unique_id_with_options(&options)
135            .map_err(Error::from)
136            .map(|id| ObjectId {
137                inner: id,
138                namespace: Some(self),
139            })
140    }
141}
142
143/// An ObjectId is used to identify, locate, and access a Durable Object via interaction with its
144/// Stub.
145#[derive(Debug)]
146pub struct ObjectId<'a> {
147    inner: DurableObjectId,
148    namespace: Option<&'a ObjectNamespace>,
149}
150
151impl ObjectId<'_> {
152    /// Get a Stub for the Durable Object instance identified by this ObjectId.
153    pub fn get_stub(&self) -> Result<Stub> {
154        self.namespace
155            .ok_or_else(|| JsValue::from("Cannot get stub from within a Durable Object"))
156            .and_then(|n| {
157                Ok(Stub {
158                    inner: n.inner.get(&self.inner)?,
159                })
160            })
161            .map_err(Error::from)
162    }
163
164    pub fn get_stub_with_location_hint(&self, location_hint: &str) -> Result<Stub> {
165        let options = Object::new();
166        js_sys::Reflect::set(
167            &options,
168            &JsValue::from("locationHint"),
169            &location_hint.into(),
170        )?;
171
172        self.namespace
173            .ok_or_else(|| JsValue::from("Cannot get stub from within a Durable Object"))
174            .and_then(|n| {
175                Ok(Stub {
176                    inner: n.inner.get_with_options(&self.inner, &options)?,
177                })
178            })
179            .map_err(Error::from)
180    }
181
182    /// The name that was used to create the `ObjectId` via [`id_from_name`](https://developers.cloudflare.com/durable-objects/api/namespace/#idfromname).
183    /// `None` is returned if the `ObjectId` was constructed using [`unique_id`](https://developers.cloudflare.com/durable-objects/api/namespace/#newuniqueid).
184    /// `None` is also returned within the Durable Object constructor, as the `name` property is not accessible there (see <https://github.com/cloudflare/workerd/issues/2240>).
185    pub fn name(&self) -> Option<String> {
186        self.inner.name()
187    }
188}
189
190impl PartialEq for ObjectId<'_> {
191    /// Compare equality between two ObjectIds using [`equals`](<https://developers.cloudflare.com/durable-objects/api/id/#equals>).
192    /// <div class="warning">The equality check ignores the namespace.</div>
193    fn eq(&self, other: &Self) -> bool {
194        self.inner.equals(&other.inner)
195    }
196}
197
198impl Display for ObjectId<'_> {
199    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
200        write!(
201            f,
202            "{}",
203            self.inner.to_string().map_err(|_| { std::fmt::Error })?
204        )
205    }
206}
207
208/// Passed from the runtime to provide access to the Durable Object's storage as well as various
209/// metadata about the Object.
210#[derive(Debug)]
211pub struct State {
212    inner: DurableObjectState,
213}
214
215impl State {
216    /// The ID of this Durable Object which can be converted into a hex string using its `to_string()`
217    /// method.
218    pub fn id(&self) -> ObjectId<'_> {
219        ObjectId {
220            inner: self.inner.id().unwrap(),
221            namespace: None,
222        }
223    }
224
225    /// Contains methods for accessing persistent storage via the transactional storage API. See
226    /// [Transactional Storage API](https://developers.cloudflare.com/workers/runtime-apis/durable-objects#transactional-storage-api) for a detailed reference.
227    pub fn storage(&self) -> Storage {
228        Storage {
229            inner: self.inner.storage().unwrap(),
230        }
231    }
232
233    pub fn wait_until<F>(&self, future: F)
234    where
235        F: Future<Output = ()> + 'static,
236    {
237        self.inner
238            .wait_until(&future_to_promise(async {
239                future.await;
240                Ok(JsValue::UNDEFINED)
241            }))
242            .unwrap()
243    }
244
245    // needs to be accessed by the `#[durable_object]` macro in a conversion step
246    pub fn _inner(self) -> DurableObjectState {
247        self.inner
248    }
249
250    pub fn accept_web_socket(&self, ws: &WebSocket) {
251        self.inner.accept_websocket(ws.as_ref()).unwrap()
252    }
253
254    pub fn accept_websocket_with_tags(&self, ws: &WebSocket, tags: &[&str]) {
255        let tags = tags.iter().map(|it| (*it).into()).collect();
256
257        self.inner
258            .accept_websocket_with_tags(ws.as_ref(), tags)
259            .unwrap();
260    }
261
262    pub fn get_websockets(&self) -> Vec<WebSocket> {
263        self.inner
264            .get_websockets()
265            .unwrap()
266            .into_iter()
267            .map(Into::into)
268            .collect()
269    }
270
271    pub fn get_websockets_with_tag(&self, tag: &str) -> Vec<WebSocket> {
272        self.inner
273            .get_websockets_with_tag(tag)
274            .unwrap()
275            .into_iter()
276            .map(Into::into)
277            .collect()
278    }
279
280    /// Retrieve tags from a hibernatable websocket
281    pub fn get_tags(&self, websocket: &WebSocket) -> Vec<String> {
282        self.inner.get_tags(websocket.as_ref()).unwrap()
283    }
284
285    pub fn set_websocket_auto_response(&self, pair: &worker_sys::WebSocketRequestResponsePair) {
286        self.inner.set_websocket_auto_response(pair).unwrap();
287    }
288
289    pub fn get_websocket_auto_response(&self) -> Option<worker_sys::WebSocketRequestResponsePair> {
290        self.inner.get_websocket_auto_response().unwrap()
291    }
292}
293
294impl From<DurableObjectState> for State {
295    fn from(o: DurableObjectState) -> Self {
296        Self { inner: o }
297    }
298}
299
300/// Access a Durable Object's Storage API. Each method is implicitly wrapped inside a transaction,
301/// such that its results are atomic and isolated from all other storage operations, even when
302/// accessing multiple key-value pairs.
303pub struct Storage {
304    inner: DurableObjectStorage,
305}
306
307impl core::fmt::Debug for Storage {
308    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
309        f.debug_struct("Storage").finish()
310    }
311}
312
313impl Storage {
314    /// Retrieves the value associated with the given key. The type of the returned value will be
315    /// whatever was previously written for the key.
316    ///
317    /// Returns [Err] if the key does not exist.
318    pub async fn get<T: serde::de::DeserializeOwned>(&self, key: &str) -> Result<T> {
319        JsFuture::from(self.inner.get(key)?)
320            .await
321            .and_then(|val| {
322                if val.is_undefined() {
323                    Err(JsValue::from("No such value in storage."))
324                } else {
325                    serde_wasm_bindgen::from_value(val).map_err(|e| JsValue::from(e.to_string()))
326                }
327            })
328            .map_err(Error::from)
329    }
330
331    /// Retrieves the values associated with each of the provided keys.
332    pub async fn get_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<Map> {
333        let keys = self.inner.get_multiple(
334            keys.into_iter()
335                .map(|key| JsValue::from(key.deref()))
336                .collect(),
337        )?;
338        let keys = JsFuture::from(keys).await?;
339        keys.dyn_into::<Map>().map_err(Error::from)
340    }
341
342    /// Stores the value and associates it with the given key.
343    pub async fn put<T: Serialize>(&self, key: &str, value: T) -> Result<()> {
344        self.put_raw(key, serde_wasm_bindgen::to_value(&value)?)
345            .await
346    }
347
348    pub async fn put_raw(&self, key: &str, value: impl Into<JsValue>) -> Result<()> {
349        JsFuture::from(self.inner.put(key, value.into())?)
350            .await
351            .map_err(Error::from)
352            .map(|_| ())
353    }
354
355    /// Takes a serializable struct and stores each of its keys and values to storage.
356    pub async fn put_multiple<T: Serialize>(&self, values: T) -> Result<()> {
357        let values = serde_wasm_bindgen::to_value(&values)?;
358        if !values.is_object() {
359            return Err("Must pass in a struct type".to_string().into());
360        }
361        self.put_multiple_raw(values.dyn_into().unwrap()).await
362    }
363
364    /// Takes an object and stores each of its keys and values to storage.
365    ///
366    /// ```no_run
367    /// # use worker::Storage;
368    /// use worker::JsValue;
369    ///
370    /// # let storage: Storage = todo!();
371    ///
372    /// let obj = js_sys::Object::new();
373    /// js_sys::Reflect::set(&obj, &JsValue::from_str("foo"), JsValue::from_u64(1));
374    ///
375    /// storage.put_multiple_raw(obj);
376    /// ```
377    pub async fn put_multiple_raw(&self, values: Object) -> Result<()> {
378        JsFuture::from(self.inner.put_multiple(values.into())?)
379            .await
380            .map_err(Error::from)
381            .map(|_| ())
382    }
383
384    /// Deletes the key and associated value. Returns true if the key existed or false if it didn't.
385    pub async fn delete(&self, key: &str) -> Result<bool> {
386        let fut: JsFuture = self.inner.delete(key)?.into();
387        fut.await
388            .and_then(|jsv| {
389                jsv.as_bool()
390                    .ok_or_else(|| JsValue::from("Promise did not return bool"))
391            })
392            .map_err(Error::from)
393    }
394
395    /// Deletes the provided keys and their associated values. Returns a count of the number of
396    /// key-value pairs deleted.
397    pub async fn delete_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<usize> {
398        let fut: JsFuture = self
399            .inner
400            .delete_multiple(
401                keys.into_iter()
402                    .map(|key| JsValue::from(key.deref()))
403                    .collect(),
404            )?
405            .into();
406        fut.await
407            .and_then(|jsv| {
408                jsv.as_f64()
409                    .map(|f| f as usize)
410                    .ok_or_else(|| JsValue::from("Promise did not return number"))
411            })
412            .map_err(Error::from)
413    }
414
415    /// Deletes all keys and associated values, effectively deallocating all storage used by the
416    /// Durable Object. In the event of a failure while the operation is still in flight, it may be
417    /// that only a subset of the data is properly deleted.
418    pub async fn delete_all(&self) -> Result<()> {
419        let fut: JsFuture = self.inner.delete_all()?.into();
420        fut.await.map(|_| ()).map_err(Error::from)
421    }
422
423    /// Returns all keys and values associated with the current Durable Object in ascending
424    /// lexicographic sorted order.
425    ///
426    /// Be aware of how much data may be stored in your Durable Object before calling this version
427    /// of list without options, because it will all be loaded into the Durable Object's memory,
428    /// potentially hitting its [limit](https://developers.cloudflare.com/workers/platform/limits#durable-objects-limits).
429    /// If that is a concern, use the alternate `list_with_options()` method.
430    pub async fn list(&self) -> Result<Map> {
431        let fut: JsFuture = self.inner.list()?.into();
432        fut.await
433            .and_then(|jsv| jsv.dyn_into())
434            .map_err(Error::from)
435    }
436
437    /// Returns keys associated with the current Durable Object according to the parameters in the
438    /// provided options object.
439    pub async fn list_with_options(&self, opts: ListOptions<'_>) -> Result<Map> {
440        let fut: JsFuture = self
441            .inner
442            .list_with_options(serde_wasm_bindgen::to_value(&opts)?.into())?
443            .into();
444        fut.await
445            .and_then(|jsv| jsv.dyn_into())
446            .map_err(Error::from)
447    }
448
449    /// Retrieves the current alarm time (if set) as integer milliseconds since epoch.
450    /// The alarm is considered to be set if it has not started, or if it has failed
451    /// and any retry has not begun. If no alarm is set, `get_alarm()` returns `None`.
452    pub async fn get_alarm(&self) -> Result<Option<i64>> {
453        let fut: JsFuture = self.inner.get_alarm(JsValue::NULL.into())?.into();
454        fut.await
455            .map(|jsv| jsv.as_f64().map(|f| f as i64))
456            .map_err(Error::from)
457    }
458
459    pub async fn get_alarm_with_options(&self, options: GetAlarmOptions) -> Result<Option<i64>> {
460        let fut: JsFuture = self
461            .inner
462            .get_alarm(serde_wasm_bindgen::to_value(&options)?.into())?
463            .into();
464        fut.await
465            .map(|jsv| jsv.as_f64().map(|f| f as i64))
466            .map_err(Error::from)
467    }
468
469    /// Sets the current alarm time to the given datetime.
470    ///
471    /// If `set_alarm()` is called with a time equal to or before Date.now(), the alarm
472    /// will be scheduled for asynchronous execution in the immediate future. If the
473    /// alarm handler is currently executing in this case, it will not be canceled.
474    /// Alarms can be set to millisecond granularity and will usually execute within
475    /// a few milliseconds after the set time, but can be delayed by up to a minute
476    /// due to maintenance or failures while failover takes place.
477    pub async fn set_alarm(&self, scheduled_time: impl Into<ScheduledTime>) -> Result<()> {
478        let fut: JsFuture = self
479            .inner
480            .set_alarm(scheduled_time.into().schedule(), JsValue::NULL.into())?
481            .into();
482        fut.await.map(|_| ()).map_err(Error::from)
483    }
484
485    pub async fn set_alarm_with_options(
486        &self,
487        scheduled_time: impl Into<ScheduledTime>,
488        options: SetAlarmOptions,
489    ) -> Result<()> {
490        let fut: JsFuture = self
491            .inner
492            .set_alarm(
493                scheduled_time.into().schedule(),
494                serde_wasm_bindgen::to_value(&options)?.into(),
495            )?
496            .into();
497        fut.await.map(|_| ()).map_err(Error::from)
498    }
499
500    /// Deletes the alarm if one exists. Does not cancel the alarm handler if it is
501    /// currently executing.
502    pub async fn delete_alarm(&self) -> Result<()> {
503        let fut: JsFuture = self.inner.delete_alarm(JsValue::NULL.into())?.into();
504        fut.await.map(|_| ()).map_err(Error::from)
505    }
506
507    pub async fn delete_alarm_with_options(&self, options: SetAlarmOptions) -> Result<()> {
508        let fut: JsFuture = self
509            .inner
510            .delete_alarm(serde_wasm_bindgen::to_value(&options)?.into())?
511            .into();
512        fut.await.map(|_| ()).map_err(Error::from)
513    }
514
515    pub async fn transaction<F, Fut>(&self, closure: F) -> Result<()>
516    where
517        F: FnOnce(Transaction) -> Fut + 'static,
518        Fut: Future<Output = Result<()>> + 'static,
519    {
520        let inner: Box<dyn FnOnce(DurableObjectTransaction) -> js_sys::Promise> =
521            Box::new(move |t: DurableObjectTransaction| -> js_sys::Promise {
522                future_to_promise(async move {
523                    closure(Transaction { inner: t })
524                        .await
525                        .map_err(JsValue::from)
526                        .map(|_| JsValue::NULL)
527                })
528            });
529        let clos = wasm_bindgen::closure::Closure::once(inner);
530        JsFuture::from(self.inner.transaction(&clos)?)
531            .await
532            .map_err(Error::from)
533            .map(|_| ())
534    }
535
536    // Add new method to access SQLite APIs
537    pub fn sql(&self) -> crate::sql::SqlStorage {
538        crate::sql::SqlStorage::new(self.inner.sql())
539    }
540}
541
542#[derive(Debug)]
543pub struct Transaction {
544    inner: DurableObjectTransaction,
545}
546
547impl Transaction {
548    pub async fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T> {
549        JsFuture::from(self.inner.get(key)?)
550            .await
551            .and_then(|val| {
552                if val.is_undefined() {
553                    Err(JsValue::from("No such value in storage."))
554                } else {
555                    serde_wasm_bindgen::from_value(val).map_err(std::convert::Into::into)
556                }
557            })
558            .map_err(Error::from)
559    }
560
561    pub async fn get_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<Map> {
562        let keys = self.inner.get_multiple(
563            keys.into_iter()
564                .map(|key| JsValue::from(key.deref()))
565                .collect(),
566        )?;
567        let keys = JsFuture::from(keys).await?;
568        keys.dyn_into::<Map>().map_err(Error::from)
569    }
570
571    pub async fn put<T: Serialize>(&self, key: &str, value: T) -> Result<()> {
572        JsFuture::from(self.inner.put(key, serde_wasm_bindgen::to_value(&value)?)?)
573            .await
574            .map_err(Error::from)
575            .map(|_| ())
576    }
577
578    // Each key-value pair in the serialized object will be added to the storage
579    pub async fn put_multiple<T: Serialize>(&self, values: T) -> Result<()> {
580        let values = serde_wasm_bindgen::to_value(&values)?;
581        if !values.is_object() {
582            return Err("Must pass in a struct type".to_string().into());
583        }
584        JsFuture::from(self.inner.put_multiple(values)?)
585            .await
586            .map_err(Error::from)
587            .map(|_| ())
588    }
589
590    pub async fn delete(&self, key: &str) -> Result<bool> {
591        let fut: JsFuture = self.inner.delete(key)?.into();
592        fut.await
593            .and_then(|jsv| {
594                jsv.as_bool()
595                    .ok_or_else(|| JsValue::from("Promise did not return bool"))
596            })
597            .map_err(Error::from)
598    }
599
600    pub async fn delete_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<usize> {
601        let fut: JsFuture = self
602            .inner
603            .delete_multiple(
604                keys.into_iter()
605                    .map(|key| JsValue::from(key.deref()))
606                    .collect(),
607            )?
608            .into();
609        fut.await
610            .and_then(|jsv| {
611                jsv.as_f64()
612                    .map(|f| f as usize)
613                    .ok_or_else(|| JsValue::from("Promise did not return number"))
614            })
615            .map_err(Error::from)
616    }
617
618    pub async fn delete_all(&self) -> Result<()> {
619        let fut: JsFuture = self.inner.delete_all()?.into();
620        fut.await.map(|_| ()).map_err(Error::from)
621    }
622
623    pub async fn list(&self) -> Result<Map> {
624        let fut: JsFuture = self.inner.list()?.into();
625        fut.await
626            .and_then(|jsv| jsv.dyn_into())
627            .map_err(Error::from)
628    }
629
630    pub async fn list_with_options(&self, opts: ListOptions<'_>) -> Result<Map> {
631        let fut: JsFuture = self
632            .inner
633            .list_with_options(serde_wasm_bindgen::to_value(&opts)?.into())?
634            .into();
635        fut.await
636            .and_then(|jsv| jsv.dyn_into())
637            .map_err(Error::from)
638    }
639
640    pub fn rollback(&self) -> Result<()> {
641        self.inner.rollback().map_err(Error::from)
642    }
643}
644
645#[derive(Default, Serialize, Debug)]
646pub struct ListOptions<'a> {
647    /// Key at which the list results should start, inclusive.
648    #[serde(skip_serializing_if = "Option::is_none")]
649    start: Option<&'a str>,
650    /// Key at which the list results should end, exclusive.
651    #[serde(skip_serializing_if = "Option::is_none")]
652    end: Option<&'a str>,
653    /// Restricts results to only include key-value pairs whose keys begin with the prefix.
654    #[serde(skip_serializing_if = "Option::is_none")]
655    prefix: Option<&'a str>,
656    /// If true, return results in descending lexicographic order instead of the default ascending
657    /// order.
658    #[serde(skip_serializing_if = "Option::is_none")]
659    reverse: Option<bool>,
660    /// Maximum number of key-value pairs to return.
661    #[serde(skip_serializing_if = "Option::is_none")]
662    limit: Option<usize>,
663}
664
665impl<'a> ListOptions<'a> {
666    /// Create a new ListOptions struct with no options set.
667    pub fn new() -> Self {
668        Default::default()
669    }
670
671    /// Key at which the list results should start, inclusive.
672    pub fn start(mut self, val: &'a str) -> Self {
673        self.start = Some(val);
674        self
675    }
676
677    /// Key at which the list results should end, exclusive.
678    pub fn end(mut self, val: &'a str) -> Self {
679        self.end = Some(val);
680        self
681    }
682
683    /// Restricts results to only include key-value pairs whose keys begin with the prefix.
684    pub fn prefix(mut self, val: &'a str) -> Self {
685        self.prefix = Some(val);
686        self
687    }
688
689    /// If true, return results in descending lexicographic order instead of the default ascending
690    /// order.
691    pub fn reverse(mut self, val: bool) -> Self {
692        self.reverse = Some(val);
693        self
694    }
695
696    /// Maximum number of key-value pairs to return.
697    pub fn limit(mut self, val: usize) -> Self {
698        self.limit = Some(val);
699        self
700    }
701}
702#[derive(Debug)]
703enum ScheduledTimeInit {
704    Date(js_sys::Date),
705    Offset(f64),
706}
707
708/// Determines when a Durable Object alarm should be ran, based on a timestamp or offset in milliseconds.
709///
710/// Implements [`From`] for:
711/// - [`Duration`], interpreted as an offset (in milliseconds).
712/// - [`i64`], interpreted as an offset (in milliseconds).
713/// - [`DateTime`], interpreted as a timestamp.
714///
715/// When an offset is used, the time at which `set_alarm()` or `set_alarm_with_options()` is called
716/// is used to compute the scheduled time. [`Date::now`] is used as the current time.
717#[derive(Debug)]
718pub struct ScheduledTime {
719    init: ScheduledTimeInit,
720}
721
722impl ScheduledTime {
723    pub fn new(date: js_sys::Date) -> Self {
724        Self {
725            init: ScheduledTimeInit::Date(date),
726        }
727    }
728
729    fn schedule(self) -> js_sys::Date {
730        match self.init {
731            ScheduledTimeInit::Date(date) => date,
732            ScheduledTimeInit::Offset(offset_ms) => {
733                let now = Date::now().as_millis() as f64;
734                js_sys::Date::new(&Number::from(now + offset_ms))
735            }
736        }
737    }
738}
739
740impl From<i64> for ScheduledTime {
741    fn from(offset_ms: i64) -> Self {
742        ScheduledTime {
743            init: ScheduledTimeInit::Offset(offset_ms as f64),
744        }
745    }
746}
747
748impl From<DateTime<Utc>> for ScheduledTime {
749    fn from(date: DateTime<Utc>) -> Self {
750        ScheduledTime {
751            init: ScheduledTimeInit::Date(js_sys::Date::new(&Number::from(
752                date.timestamp_millis() as f64,
753            ))),
754        }
755    }
756}
757
758impl From<Duration> for ScheduledTime {
759    fn from(offset: Duration) -> Self {
760        ScheduledTime {
761            init: ScheduledTimeInit::Offset(offset.as_millis() as f64),
762        }
763    }
764}
765
766#[derive(Debug, Clone, Default, Serialize)]
767pub struct GetAlarmOptions {
768    #[serde(skip_serializing_if = "Option::is_none")]
769    pub allow_concurrency: Option<bool>,
770}
771
772#[derive(Debug, Clone, Default, Serialize)]
773pub struct SetAlarmOptions {
774    #[serde(skip_serializing_if = "Option::is_none")]
775    pub allow_concurrency: Option<bool>,
776    #[serde(skip_serializing_if = "Option::is_none")]
777    pub allow_unconfirmed: Option<bool>,
778}
779
780impl EnvBinding for ObjectNamespace {
781    const TYPE_NAME: &'static str = "DurableObjectNamespace";
782}
783
784impl JsCast for ObjectNamespace {
785    fn instanceof(val: &JsValue) -> bool {
786        val.is_instance_of::<EdgeObjectNamespace>()
787    }
788
789    fn unchecked_from_js(val: JsValue) -> Self {
790        Self { inner: val.into() }
791    }
792
793    fn unchecked_from_js_ref(val: &JsValue) -> &Self {
794        unsafe { &*(val as *const JsValue as *const Self) }
795    }
796}
797
798impl From<ObjectNamespace> for JsValue {
799    fn from(ns: ObjectNamespace) -> Self {
800        JsValue::from(ns.inner)
801    }
802}
803
804impl AsRef<JsValue> for ObjectNamespace {
805    fn as_ref(&self) -> &JsValue {
806        &self.inner
807    }
808}
809
810#[derive(Debug)]
811pub enum WebSocketIncomingMessage {
812    String(String),
813    Binary(Vec<u8>),
814}
815
816/**
817**Note:** Implement this trait with a standard `impl DurableObject for YourType` block, but in order to
818integrate them with the Workers Runtime, you must also add the **`#[durable_object]`** attribute
819to the struct.
820
821## Example
822```no_run
823use worker::*;
824
825#[durable_object]
826pub struct Chatroom {
827    users: Vec<User>,
828    messages: Vec<Message>,
829    state: State,
830    env: Env, // access `Env` across requests, use inside `fetch`
831}
832
833impl DurableObject for Chatroom {
834    fn new(state: State, env: Env) -> Self {
835        Self {
836            users: vec![],
837            messages: vec![],
838            state,
839            env,
840        }
841    }
842
843    async fn fetch(&self, _req: Request) -> Result<Response> {
844        // do some work when a worker makes a request to this DO
845        Response::ok(&format!("{} active users.", self.users.len()))
846    }
847}
848```
849*/
850#[allow(async_fn_in_trait)] // Send is not needed
851pub trait DurableObject: has_durable_object_attribute {
852    fn new(state: State, env: Env) -> Self;
853
854    async fn fetch(&self, req: Request) -> Result<Response>;
855
856    #[allow(clippy::diverging_sub_expression)]
857    async fn alarm(&self) -> Result<Response> {
858        worker_sys::console_error!("alarm() handler not implemented");
859        unimplemented!("alarm() handler")
860    }
861
862    #[allow(unused_variables, clippy::diverging_sub_expression)]
863    async fn websocket_message(
864        &self,
865        ws: WebSocket,
866        message: WebSocketIncomingMessage,
867    ) -> Result<()> {
868        worker_sys::console_error!("websocket_message() handler not implemented");
869        unimplemented!("websocket_message() handler")
870    }
871
872    #[allow(unused_variables, clippy::diverging_sub_expression)]
873    async fn websocket_close(
874        &self,
875        ws: WebSocket,
876        code: usize,
877        reason: String,
878        was_clean: bool,
879    ) -> Result<()> {
880        worker_sys::console_error!("websocket_close() handler not implemented");
881        unimplemented!("websocket_close() handler")
882    }
883
884    #[allow(unused_variables, clippy::diverging_sub_expression)]
885    async fn websocket_error(&self, ws: WebSocket, error: Error) -> Result<()> {
886        worker_sys::console_error!("websocket_error() handler not implemented");
887        unimplemented!("websocket_error() handler")
888    }
889}
890
891#[doc(hidden)]
892#[allow(non_camel_case_types)]
893pub trait has_durable_object_attribute {}