azure_functions/bindings/
durable_activity_context.rs

1use crate::rpc::{typed_data::Data, TypedData};
2use serde::Deserialize;
3use serde_json::{from_str, Number, Value};
4use std::collections::HashMap;
5
6const INSTANCE_ID_KEY: &str = "instanceId";
7
8/// Represents the Durable Functions activity context binding.
9///
10/// The following binding attributes are supported:
11///
12/// | Name       | Description                                                      |
13/// |------------|------------------------------------------------------------------|
14/// | `name`     | The name of the parameter being bound.                           |
15/// | `activity` | The name of the activity.  Defaults to the name of the function. |
16///
17/// # Examples
18///
19/// An activity that outputs a string:
20///
21/// ```rust
22/// use azure_functions::{bindings::DurableActivityContext, durable::ActivityOutput, func};
23///
24/// #[func]
25/// pub fn say_hello(context: DurableActivityContext) -> ActivityOutput {
26///     format!(
27///         "Hello {}!",
28///         context.input.as_str().expect("expected a string input")
29///     )
30///     .into()
31/// }
32/// ```
33#[derive(Debug, Clone, Deserialize)]
34#[serde(rename_all = "camelCase")]
35pub struct DurableActivityContext {
36    /// The input to the activity function.
37    pub input: Value,
38    /// The orchestration instance identifier.
39    pub instance_id: String,
40}
41
42impl DurableActivityContext {
43    #[doc(hidden)]
44    pub fn new(data: TypedData, mut metadata: HashMap<String, TypedData>) -> Self {
45        DurableActivityContext {
46            input: match data.data {
47                Some(Data::String(s)) => Value::String(s),
48                Some(Data::Json(s)) => from_str(&s).unwrap_or_default(),
49                Some(Data::Int(i)) => Value::Number(i.into()),
50                Some(Data::Double(d)) => Value::Number(Number::from_f64(d).unwrap()),
51                _ => Value::Null,
52            },
53            instance_id: metadata
54                .remove(INSTANCE_ID_KEY)
55                .map(|data| match data.data {
56                    Some(Data::String(s)) => s,
57                    _ => panic!("expected a string for instance id"),
58                })
59                .expect("expected an instance id"),
60        }
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use crate::rpc::typed_data::Data;
68
69    #[test]
70    fn it_constructs() {
71        let data = TypedData {
72            data: Some(Data::String("bar".to_string())),
73        };
74
75        let mut metadata = HashMap::new();
76        metadata.insert(
77            INSTANCE_ID_KEY.to_string(),
78            TypedData {
79                data: Some(Data::String("foo".to_string())),
80            },
81        );
82
83        let context = DurableActivityContext::new(data, metadata);
84        assert_eq!(context.instance_id, "foo");
85        assert_eq!(context.input, Value::String("bar".to_string()));
86    }
87}