1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::{rpc::TypedData, util::convert_from};
use serde_json::Value;
use std::collections::HashMap;

/// Represents a Cosmos DB trigger binding.
///
/// The following binding attributes are supported:
///
/// | Name                          | Description                                                                                                                                                                                                                                                                                                                      |
/// |-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
/// | `name`                        | The name of the parameter being bound.                                                                                                                                                                                                                                                                                           |
/// | `connection`                  | The name of an app setting that contains the connection string used to connect to the Azure Cosmos DB account being monitored.                                                                                                                                                                                                   |
/// | `database_name`               | The name of the Azure Cosmos DB database with the collection being monitored.                                                                                                                                                                                                                                                    |
/// | `collection_name`             | The name of the collection being monitored.                                                                                                                                                                                                                                                                                      |
/// | `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.                                                                                                                                                                    |
/// | `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.                                                                                                                                                                                         |
/// | `create_lease_collection`     | When set to true, the leases collection is automatically created when it doesn't already exist. The default value is false.                                                                                                                                                                                                      |
/// | `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.                                                                                                                                                         |
/// | `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.                                                                                                                    |
/// | `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).                                                                                                                                                 |
/// | `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).                                                                                                                                                |
/// | `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).                                  |
/// | `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).                                                                                                                                                                            |
/// | `checkpoint_frequency`        | When set, it defines, in milliseconds, the interval between lease checkpoints. Default is always after each Function call.                                                                                                                                                                                                       |
/// | `max_items_per_invocation`    | When set, it customizes the maximum amount of items received per Function call.                                                                                                                                                                                                                                                  |
/// | `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. |
///
/// # Examples
///
/// An example of logging all Cosmos DB documents that triggered the function:
///
/// ```rust
/// use azure_functions::{
///     bindings::CosmosDbTrigger,
///     func,
/// };
/// use log::info;
///
/// #[func]
/// #[binding(
///     name = "trigger",
///     connection = "myconnection",
///     database_name = "mydb",
///     collection_name = "mycollection"
/// )]
/// pub fn log_documents(trigger: CosmosDbTrigger) {
///     for document in trigger.documents {
///         info!("{}", document);
///     }
/// }
/// ```
#[derive(Debug)]
pub struct CosmosDbTrigger {
    /// The Cosmos DB documents that triggered the function.
    pub documents: Vec<Value>,
}

impl CosmosDbTrigger {
    #[doc(hidden)]
    pub fn new(data: TypedData, _metadata: HashMap<String, TypedData>) -> Self {
        let value = convert_from(&data).expect("expected JSON document data");
        match value {
            Value::Array(array) => CosmosDbTrigger { documents: array },
            _ => panic!("expected a JSON array for Cosmos DB trigger data"),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::rpc::typed_data::Data;

    #[test]
    fn it_constructs() {
        const DOCUMENTS: &'static str = r#"[
            {
                "id": "id1",
                "_etag": "etag1",
                "_rid": "rid1",
                "_self": "self1",
                "_ts": 1,
                "data": "value1"
            },
            {
                "id": "id2",
                "_etag": "etag2",
                "_rid": "rid2",
                "_self": "self2",
                "_ts": 2,
                "data": "value2"
            },
            {
                "id": "id3",
                "_etag": "etag3",
                "_rid": "rid3",
                "_self": "self3",
                "_ts": 3,
                "data": "value3"
            }
        ]"#;

        let data = TypedData {
            data: Some(Data::Json(DOCUMENTS.to_string())),
        };

        let trigger = CosmosDbTrigger::new(data, HashMap::new());

        let documents = trigger.documents;
        assert_eq!(documents.len(), 3);

        assert_eq!(documents[0]["id"].as_str().unwrap(), "id1");
        assert_eq!(documents[0]["_etag"].as_str().unwrap(), "etag1");
        assert_eq!(documents[0]["_rid"].as_str().unwrap(), "rid1");
        assert_eq!(documents[0]["_self"].as_str().unwrap(), "self1");
        assert_eq!(documents[0]["_ts"].as_i64().unwrap(), 1);
        assert_eq!(documents[0]["data"].as_str().unwrap(), "value1");

        assert_eq!(documents[1]["id"].as_str().unwrap(), "id2");
        assert_eq!(documents[1]["_etag"].as_str().unwrap(), "etag2");
        assert_eq!(documents[1]["_rid"].as_str().unwrap(), "rid2");
        assert_eq!(documents[1]["_self"].as_str().unwrap(), "self2");
        assert_eq!(documents[1]["_ts"].as_i64().unwrap(), 2);
        assert_eq!(documents[1]["data"].as_str().unwrap(), "value2");

        assert_eq!(documents[2]["id"].as_str().unwrap(), "id3");
        assert_eq!(documents[2]["_etag"].as_str().unwrap(), "etag3");
        assert_eq!(documents[2]["_rid"].as_str().unwrap(), "rid3");
        assert_eq!(documents[2]["_self"].as_str().unwrap(), "self3");
        assert_eq!(documents[2]["_ts"].as_i64().unwrap(), 3);
        assert_eq!(documents[2]["data"].as_str().unwrap(), "value3");
    }
}