Skip to content
This repository was archived by the owner on Oct 6, 2020. It is now read-only.

Commit d93ff51

Browse files
author
Francesco Cogno
authored
Expose CosmosDB methods as traits (#281)
1 parent 6ee5f46 commit d93ff51

File tree

149 files changed

+8164
-4596
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

149 files changed

+8164
-4596
lines changed

README.md

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
[![Build Status](https://travis-ci.org/MindFlavor/AzureSDKForRust.svg?branch=master)](https://travis-ci.org/MindFlavor/AzureSDKForRust) [![Coverage Status](https://coveralls.io/repos/MindFlavor/AzureSDKForRust/badge.svg?branch=master&service=github)](https://coveralls.io/github/MindFlavor/AzureSDKForRust?branch=master) ![stability-unstable](https://img.shields.io/badge/stability-unstable-yellow.svg)
77

8-
[![tag](https://img.shields.io/github/tag/mindflavor/AzureSDKForRust.svg)](https://github.com/MindFlavor/AzureSDKForRust/tree/cosmos_0.43.1) [![release](https://img.shields.io/github/release/mindflavor/AzureSDKForRust.svg)](https://github.com/MindFlavor/AzureSDKForRust/releases/tag/cosmos_0.43.1) [![commitssince](https://img.shields.io/github/commits-since/mindflavor/AzureSDKForRust/cosmos_0.43.1)](https://github.com/MindFlavor/AzureSDKForRust/commits/master)
8+
[![tag](https://img.shields.io/github/tag/mindflavor/AzureSDKForRust.svg)](https://github.com/MindFlavor/AzureSDKForRust/tree/cosmos_0.100.0) [![release](https://img.shields.io/github/release/mindflavor/AzureSDKForRust.svg)](https://github.com/MindFlavor/AzureSDKForRust/releases/tag/cosmos_0.100.0) [![commitssince](https://img.shields.io/github/commits-since/mindflavor/AzureSDKForRust/cosmos_0.100.0)](https://github.com/MindFlavor/AzureSDKForRust/commits/master)
99

1010
[![GitHub contributors](https://img.shields.io/github/contributors/MindFlavor/AzureSDKForRust.svg)](https://github.com/MindFlavor/AzureSDKForRust/graphs/contributors)
1111

@@ -50,7 +50,7 @@ You can find examples in the [```examples```](https://github.com/MindFlavor/Azur
5050
```rust
5151
#[macro_use]
5252
extern crate serde_derive;
53-
// Using the prelude module of the CosmosDB crate makes easier to use the Rust Azure SDK for Cosmos
53+
// Using the prelude module of the Cosmos crate makes easier to use the Rust Azure SDK for Cosmos
5454
// DB.
5555
use azure_sdk_core::prelude::*;
5656
use azure_sdk_cosmos::prelude::*;
@@ -97,14 +97,15 @@ async fn main() -> Result<(), Box<dyn Error>> {
9797
let authorization_token = AuthorizationToken::new_master(&master_key)?;
9898

9999
// Next we will create a Cosmos client.
100-
let client = ClientBuilder::new(account, authorization_token.clone())?;
100+
let client = ClientBuilder::new(account, authorization_token)?;
101101
// We know the database so we can obtain a database client.
102-
let database_client = client.with_database(&database_name);
102+
let database_client = client.with_database_client(database_name);
103103
// We know the collection so we can obtain a collection client.
104-
let collection_client = database_client.with_collection(&collection_name);
104+
let collection_client = database_client.with_collection_client(collection_name);
105105

106106
// TASK 1 - Insert 10 documents
107107
println!("Inserting 10 documents...");
108+
let mut session_token = None;
108109
for i in 0..10 {
109110
// define the document.
110111
let document_to_insert = Document::new(MySampleStruct {
@@ -114,31 +115,42 @@ async fn main() -> Result<(), Box<dyn Error>> {
114115
a_timestamp: chrono::Utc::now().timestamp(),
115116
});
116117

117-
// insert it!
118-
collection_client
119-
.create_document()
120-
.with_document(&document_to_insert)
121-
.with_partition_keys(PartitionKeys::new().push(&document_to_insert.document.a_number)?)
122-
.with_is_upsert(true) // this option will overwrite a preexisting document (if any)
123-
.execute()
124-
.await?;
118+
// insert it and store the returned session token for later use!
119+
session_token = Some(
120+
collection_client
121+
.create_document()
122+
.with_partition_keys(
123+
PartitionKeys::new().push(&document_to_insert.document.a_number)?,
124+
)
125+
.with_is_upsert(true) // this option will overwrite a preexisting document (if any)
126+
.execute_with_document(&document_to_insert)
127+
.await?
128+
.session_token, // get only the session token, if everything else was ok!
129+
);
125130
}
126131
// wow that was easy and fast, wasnt'it? :)
127132
println!("Done!");
128133

134+
let session_token = ConsistencyLevel::from(session_token.unwrap());
135+
129136
// TASK 2
130-
println!("\nStreaming documents");
131-
// we limit the number of documents to 3 for each batch as a demonstration. In practice
132-
// you will use a more sensible number (or accept the Azure default).
133-
let stream = collection_client.list_documents().with_max_item_count(3);
134-
let mut stream = Box::pin(stream.stream::<MySampleStruct>());
135-
// TODO: As soon as the streaming functionality is stabilized
136-
// in Rust we can substitute this while let Some... into
137-
// for each (or whatever the Rust team picks).
138-
while let Some(res) = stream.next().await {
139-
let res = res?;
140-
println!("Received {} documents in one batch!", res.documents.len());
141-
res.documents.iter().for_each(|doc| println!("{:#?}", doc));
137+
{
138+
println!("\nStreaming documents");
139+
// we limit the number of documents to 3 for each batch as a demonstration. In practice
140+
// you will use a more sensible number (or accept the Azure default).
141+
let stream = collection_client
142+
.list_documents()
143+
.with_consistency_level(session_token.clone())
144+
.with_max_item_count(3);
145+
let mut stream = Box::pin(stream.stream::<MySampleStruct>());
146+
// TODO: As soon as the streaming functionality is stabilized
147+
// in Rust we can substitute this while let Some... into
148+
// for each (or whatever the Rust team picks).
149+
while let Some(res) = stream.next().await {
150+
let res = res?;
151+
println!("Received {} documents in one batch!", res.documents.len());
152+
res.documents.iter().for_each(|doc| println!("{:#?}", doc));
153+
}
142154
}
143155

144156
// TASK 3
@@ -147,6 +159,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
147159
.query_documents()
148160
.with_query(&("SELECT * FROM A WHERE A.a_number < 600".into())) // there are other ways to construct a query, this is the simplest.
149161
.with_query_cross_partition(true) // this will perform a cross partition query! notice how simple it is!
162+
.with_consistency_level(session_token)
150163
.execute::<MySampleStruct>() // This will make sure the result is our custom struct!
151164
.await?
152165
.into_documents() // queries can return Documents or Raw json (ie without etag, _rid, etc...). Since our query return docs we convert with this function.
@@ -165,6 +178,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
165178
});
166179

167180
// TASK 4
181+
let session_token = ConsistencyLevel::from(query_documents_response.session_token.clone());
168182
for ref document in query_documents_response.results {
169183
// From our query above we are sure to receive a Document.
170184
println!(
@@ -174,11 +188,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
174188

175189
// to spice the delete a little we use optimistic concurreny
176190
collection_client
177-
.with_document(
178-
&document.result.id,
179-
PartitionKeys::new().push(&document.result.a_number)?,
180-
)
191+
.with_document_client(&document.result.id as &str, document.result.a_number.into())
181192
.delete_document()
193+
.with_consistency_level(session_token.clone())
182194
.with_if_match_condition((&document.document_attributes).into())
183195
.execute()
184196
.await?;
@@ -188,6 +200,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
188200
// Now the list documents should return 4 documents!
189201
let list_documents_response = collection_client
190202
.list_documents()
203+
.with_consistency_level(session_token)
191204
.execute::<serde_json::Value>() // you can use this if you don't know/care about the return type!
192205
.await?;
193206
assert_eq!(list_documents_response.documents.len(), 4);

azure_sdk_cosmos/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "azure_sdk_cosmos"
3-
version = "0.43.1"
3+
version = "0.100.0"
44
description = "Rust wrappers around Microsoft Azure REST APIs - Azure Cosmos DB crate"
55
readme = "README.md"
66
authors = ["Francesco Cogno <francesco.cogno@outlook.com>", "Max Gortman <mgortman@microsoft.com>"]

azure_sdk_cosmos/examples/attachments00.rs renamed to azure_sdk_cosmos/examples/attachments_00.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
3737
let authorization_token = AuthorizationToken::new_master(&master_key)?;
3838

3939
let client = ClientBuilder::new(account, authorization_token)?;
40-
let client = client.with_database(&database_name);
41-
let client = client.with_collection(&collection_name);
40+
let client = client.into_database_client(database_name);
41+
let client = client.into_collection_client(collection_name);
4242

4343
let id = format!("unique_id{}", 100);
4444

@@ -52,9 +52,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
5252
// let's add an entity.
5353
match client
5454
.create_document()
55-
.with_document(&doc)
5655
.with_partition_keys(PartitionKeys::new().push(&doc.document.id)?)
57-
.execute()
56+
.execute_with_document(&doc)
5857
.await
5958
{
6059
Ok(_) => {
@@ -67,15 +66,15 @@ async fn main() -> Result<(), Box<dyn Error>> {
6766

6867
let mut partition_keys = PartitionKeys::new();
6968
partition_keys.push(&doc.document.id)?;
70-
let document_client = client.with_document(&id, &partition_keys);
69+
let document_client = client.with_document_client(id, partition_keys);
7170

7271
// list attachments
7372
let ret = document_client.list_attachments().execute().await?;
7473
println!("list attachments == {:#?}", ret);
7574

7675
// reference attachment
7776
println!("creating");
78-
let attachment_client = document_client.with_attachment(&"myref03");
77+
let attachment_client = document_client.with_attachment_client("myref06");
7978
let resp = attachment_client
8079
.create_reference()
8180
.with_consistency_level((&ret).into())
@@ -91,8 +90,17 @@ async fn main() -> Result<(), Box<dyn Error>> {
9190
// sure to find the just created attachment
9291
let session_token: ConsistencyLevel = resp.into();
9392

93+
let resp = attachment_client
94+
.get()
95+
.with_consistency_level(session_token)
96+
.execute()
97+
.await?;
98+
99+
println!("get attachment == {:#?}", resp);
100+
let session_token: ConsistencyLevel = resp.into();
101+
94102
println!("replacing");
95-
let attachment_client = document_client.with_attachment(&"myref03");
103+
let attachment_client = document_client.with_attachment_client("myref06");
96104
let resp = attachment_client
97105
.replace_reference()
98106
.with_consistency_level(session_token)
@@ -114,7 +122,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
114122

115123
// slug attachment
116124
println!("creating slug attachment");
117-
let attachment_client = document_client.with_attachment(&"slug00");
125+
let attachment_client = document_client.with_attachment_client("slug00");
118126
let resp = attachment_client
119127
.create_slug()
120128
.with_consistency_level((&resp_delete).into())

azure_sdk_cosmos/examples/collection.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
2222
// Once we have an authorization token you can create a client instance. You can change the
2323
// authorization token at later time if you need, for example, to escalate the privileges for a
2424
// single operation.
25-
let client = ClientBuilder::new(account.clone(), authorization_token)?;
25+
let client = ClientBuilder::new(&account, authorization_token)?;
2626

2727
// The Cosmos' client exposes a lot of methods. This one lists the databases in the specified
2828
// account. Database do not implement Display but deref to &str so you can pass it to methods
@@ -39,7 +39,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
3939
if let Some(db) = databases.databases.first() {
4040
println!("getting info of database {}", &db.id);
4141
let db = client
42-
.with_database(&db.id)
42+
.with_database_client(&db.id)
4343
.get_database()
4444
.execute()
4545
.await?;
@@ -50,7 +50,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
5050
// list_collection method.
5151
for db in databases.databases {
5252
let collections = client
53-
.with_database(&db.id)
53+
.with_database_client(&db.id)
5454
.list_collections()
5555
.execute()
5656
.await?;
@@ -64,8 +64,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
6464
println!("\tcollection {}", collection.id);
6565

6666
let collection_response = client
67-
.with_database(&db.id)
68-
.with_collection(&collection.id)
67+
.with_database_client(&db.id)
68+
.with_collection_client(&collection.id)
6969
.get_collection()
7070
.execute()
7171
.await?;

azure_sdk_cosmos/examples/create_delete_database.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
2727
// Once we have an authorization token you can create a client instance. You can change the
2828
// authorization token at later time if you need, for example, to escalate the privileges for a
2929
// single operation.
30-
let client = ClientBuilder::new(account.clone(), authorization_token)?;
30+
let client = ClientBuilder::new(&account, authorization_token)?;
3131

3232
// The Cosmos' client exposes a lot of methods. This one lists the databases in the specified
3333
// account. Database do not implement Display but deref to &str so you can pass it to methods
@@ -45,7 +45,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
4545

4646
// create collection!
4747
{
48-
let db_client = client.with_database(&database_name);
48+
let db_client = client.with_database_client(&database_name);
4949

5050
let indexes = IncludedPathIndex {
5151
kind: KeyKind::Hash,
@@ -79,7 +79,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
7979
create_collection_response
8080
);
8181

82-
let db_collection = db_client.with_collection(&"panzadoro");
82+
let db_collection = db_client.with_collection_client("panzadoro");
8383

8484
let get_collection_response = db_collection.get_collection().execute().await?;
8585
println!("get_collection_response == {:#?}", get_collection_response);
@@ -96,7 +96,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
9696
}
9797

9898
let resp = client
99-
.with_database(&database_name)
99+
.with_database_client(&database_name)
100100
.delete_database()
101101
.execute()
102102
.await?;
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,18 @@ async fn main() -> Result<(), Box<dyn Error>> {
2222

2323
let authorization_token = AuthorizationToken::new_master(&master_key)?;
2424

25-
let client = ClientBuilder::new(account.clone(), authorization_token)?;
25+
let client = ClientBuilder::new(&account, authorization_token)?;
2626

2727
let dbs = client.list_databases().execute().await?;
2828

2929
for db in dbs.databases {
3030
println!("database == {:?}", db);
31-
let database = client.with_database(&db);
31+
let database = client.with_database_client(db.name());
3232

3333
let collections = database.list_collections().execute().await?;
3434
for collection in collections.collections {
3535
println!("collection == {:?}", collection);
36-
let collection_client = database.with_collection(&collection);
36+
let collection_client = database.with_collection_client(collection.id);
3737

3838
if collection_client.collection_name().name() == "democ" {
3939
println!("democ!");
@@ -53,10 +53,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
5353
let document = Document::new(v);
5454
let resp = collection_client
5555
.create_document()
56-
.with_document(&document)
5756
.with_partition_keys(PartitionKeys::new().push(&43u32)?)
5857
.with_is_upsert(true)
59-
.execute()
58+
.execute_with_document(&document)
6059
.await?;
6160

6261
println!("resp == {:?}", resp);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use azure_sdk_cosmos::prelude::*;
2+
use std::error::Error;
3+
4+
#[tokio::main]
5+
async fn main() -> Result<(), Box<dyn Error>> {
6+
// First we retrieve the account name and master key from environment variables.
7+
// We expect master keys (ie, not resource constrained)
8+
let master_key =
9+
std::env::var("COSMOS_MASTER_KEY").expect("Set env variable COSMOS_MASTER_KEY first!");
10+
let account = std::env::var("COSMOS_ACCOUNT").expect("Set env variable COSMOS_ACCOUNT first!");
11+
12+
let authorization_token = AuthorizationToken::new_master(&master_key)?;
13+
let cosmos_client = ClientBuilder::new(&account, authorization_token)?;
14+
//let databases = cosmos_client.list_databases().execute().await?;
15+
//println!("databases == {:#?}", databases);
16+
17+
let database_client = cosmos_client.with_database_client("pollo");
18+
println!("database_name == {}", database_client.database_name());
19+
20+
let collections = database_client.list_collections().execute().await?;
21+
println!("collections == {:#?}", collections);
22+
23+
let collection_client = database_client.with_collection_client("cnt");
24+
let collection = collection_client.get_collection().execute().await?;
25+
println!("collection == {:#?}", collection);
26+
27+
//let collection_client = database_client.with_collection(&"cnt");
28+
29+
Ok(())
30+
}

0 commit comments

Comments
 (0)