azure_functions/bindings/cosmos_db_trigger.rs
1use crate::{rpc::TypedData, util::convert_from};
2use serde_json::Value;
3use std::collections::HashMap;
4
5/// Represents a Cosmos DB trigger binding.
6///
7/// The following binding attributes are supported:
8///
9/// | Name | Description |
10/// |-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
11/// | `name` | The name of the parameter being bound. |
12/// | `connection` | The name of an app setting that contains the connection string used to connect to the Azure Cosmos DB account being monitored. |
13/// | `database_name` | The name of the Azure Cosmos DB database with the collection being monitored. |
14/// | `collection_name` | The name of the collection being monitored. |
15/// | `lease_connection` | The name of an app setting that contains the connection string to the service which holds the lease collection. When not set, the `connection` value is used. |
16/// | `lease_database_name` | The name of the database that holds the collection used to store leases. When not set, the value of the `database_name` setting is used. |
17/// | `create_lease_collection` | When set to true, the leases collection is automatically created when it doesn't already exist. The default value is false. |
18/// | `lease_collection_throughput` | Defines the amount of Request Units to assign when the leases collection is created (optional). This setting is only used when `create_lease_collection` is set to true. |
19/// | `lease_collection_prefix` | When set, it adds a prefix to the leases created in the Lease collection for this Function, effectively allowing two separate Azure Functions to share the same Lease collection by using different prefixes. |
20/// | `feed_poll_delay` | When set, it defines, in milliseconds, the delay in between polling a partition for new changes on the feed, after all current changes are drained. Default is 5000 (5 seconds). |
21/// | `lease_acquire_interval` | When set, it defines, in milliseconds, the interval to kick off a task to compute if partitions are distributed evenly among known host instances. Default is 13000 (13 seconds). |
22/// | `lease_expiration_interval` | When set, it defines, in milliseconds, the interval for which the lease is taken on a lease representing a partition. If the lease is not renewed within this interval, it will cause it to expire and ownership of the partition will move to another instance. Default is 60000 (60 seconds). |
23/// | `lease_renew_interval` | When set, it defines, in milliseconds, the renew interval for all leases for partitions currently held by an instance. Default is 17000 (17 seconds). |
24/// | `checkpoint_frequency` | When set, it defines, in milliseconds, the interval between lease checkpoints. Default is always after each Function call. |
25/// | `max_items_per_invocation` | When set, it customizes the maximum amount of items received per Function call. |
26/// | `start_from_beginning` | When set, it tells the Trigger to start reading changes from the beginning of the history of the collection instead of the current time. This only works the first time the Trigger starts, as in subsequent runs, the checkpoints are already stored. Setting this to true when there are leases already created has no effect. |
27///
28/// # Examples
29///
30/// An example of logging all Cosmos DB documents that triggered the function:
31///
32/// ```rust
33/// use azure_functions::{
34/// bindings::CosmosDbTrigger,
35/// func,
36/// };
37/// use log::info;
38///
39/// #[func]
40/// #[binding(
41/// name = "trigger",
42/// connection = "myconnection",
43/// database_name = "mydb",
44/// collection_name = "mycollection"
45/// )]
46/// pub fn log_documents(trigger: CosmosDbTrigger) {
47/// for document in trigger.documents {
48/// info!("{}", document);
49/// }
50/// }
51/// ```
52#[derive(Debug)]
53pub struct CosmosDbTrigger {
54 /// The Cosmos DB documents that triggered the function.
55 pub documents: Vec<Value>,
56}
57
58impl CosmosDbTrigger {
59 #[doc(hidden)]
60 pub fn new(data: TypedData, _metadata: HashMap<String, TypedData>) -> Self {
61 let value = convert_from(&data).expect("expected JSON document data");
62 match value {
63 Value::Array(array) => CosmosDbTrigger { documents: array },
64 _ => panic!("expected a JSON array for Cosmos DB trigger data"),
65 }
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72 use crate::rpc::typed_data::Data;
73
74 #[test]
75 fn it_constructs() {
76 const DOCUMENTS: &'static str = r#"[
77 {
78 "id": "id1",
79 "_etag": "etag1",
80 "_rid": "rid1",
81 "_self": "self1",
82 "_ts": 1,
83 "data": "value1"
84 },
85 {
86 "id": "id2",
87 "_etag": "etag2",
88 "_rid": "rid2",
89 "_self": "self2",
90 "_ts": 2,
91 "data": "value2"
92 },
93 {
94 "id": "id3",
95 "_etag": "etag3",
96 "_rid": "rid3",
97 "_self": "self3",
98 "_ts": 3,
99 "data": "value3"
100 }
101 ]"#;
102
103 let data = TypedData {
104 data: Some(Data::Json(DOCUMENTS.to_string())),
105 };
106
107 let trigger = CosmosDbTrigger::new(data, HashMap::new());
108
109 let documents = trigger.documents;
110 assert_eq!(documents.len(), 3);
111
112 assert_eq!(documents[0]["id"].as_str().unwrap(), "id1");
113 assert_eq!(documents[0]["_etag"].as_str().unwrap(), "etag1");
114 assert_eq!(documents[0]["_rid"].as_str().unwrap(), "rid1");
115 assert_eq!(documents[0]["_self"].as_str().unwrap(), "self1");
116 assert_eq!(documents[0]["_ts"].as_i64().unwrap(), 1);
117 assert_eq!(documents[0]["data"].as_str().unwrap(), "value1");
118
119 assert_eq!(documents[1]["id"].as_str().unwrap(), "id2");
120 assert_eq!(documents[1]["_etag"].as_str().unwrap(), "etag2");
121 assert_eq!(documents[1]["_rid"].as_str().unwrap(), "rid2");
122 assert_eq!(documents[1]["_self"].as_str().unwrap(), "self2");
123 assert_eq!(documents[1]["_ts"].as_i64().unwrap(), 2);
124 assert_eq!(documents[1]["data"].as_str().unwrap(), "value2");
125
126 assert_eq!(documents[2]["id"].as_str().unwrap(), "id3");
127 assert_eq!(documents[2]["_etag"].as_str().unwrap(), "etag3");
128 assert_eq!(documents[2]["_rid"].as_str().unwrap(), "rid3");
129 assert_eq!(documents[2]["_self"].as_str().unwrap(), "self3");
130 assert_eq!(documents[2]["_ts"].as_i64().unwrap(), 3);
131 assert_eq!(documents[2]["data"].as_str().unwrap(), "value3");
132 }
133}