Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions sdk/cosmos/examples/create_delete_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,10 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
};

let create_collection_response = db_client
.create_collection()
.collection_name(&"panzadoro")
.partition_key("/id")
.create_collection("/id")
.indexing_policy(ip)
.offer(Offer::Throughput(400))
.indexing_policy(&ip)
.execute()
.execute("panzadoro")
.await?;

println!(
Expand Down
8 changes: 3 additions & 5 deletions sdk/cosmos/examples/document_00.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,10 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
client
.clone()
.into_database_client(database.id.clone())
.create_collection()
.collection_name(&COLLECTION)
.create_collection("/id")
.indexing_policy(ip)
.offer(Offer::Throughput(400))
.indexing_policy(&ip)
.partition_key("/id")
.execute()
.execute(COLLECTION)
.await?
.collection
}
Expand Down
10 changes: 7 additions & 3 deletions sdk/cosmos/src/clients/database_client.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use super::*;
use crate::requests;
use crate::resources::collection::PartitionKey;
use crate::resources::ResourceType;
use crate::ReadonlyString;
use azure_core::{HttpClient, No};
use azure_core::HttpClient;

/// A client for Cosmos database resources.
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -46,8 +47,11 @@ impl DatabaseClient {
requests::DeleteDatabaseBuilder::new(self)
}

pub fn create_collection(&self) -> requests::CreateCollectionBuilder<'_, No, No, No, No> {
requests::CreateCollectionBuilder::new(self)
pub fn create_collection<'a, P: Into<PartitionKey>>(
&'a self,
partition_key: P,
) -> requests::CreateCollectionBuilder<'a> {
requests::CreateCollectionBuilder::new(self, partition_key.into())
}

pub fn list_users(&self) -> requests::ListUsersBuilder<'_, '_> {
Expand Down
196 changes: 34 additions & 162 deletions sdk/cosmos/src/requests/create_collection_builder.rs
Original file line number Diff line number Diff line change
@@ -1,190 +1,52 @@
use crate::prelude::*;
use crate::resources::collection::{Collection, IndexingPolicy, PartitionKey};
use crate::resources::collection::{IndexingPolicy, PartitionKey};
use crate::resources::ResourceType;
use crate::responses::CreateCollectionResponse;
use azure_core::prelude::*;
use azure_core::{No, ToAssign, Yes};
use http::StatusCode;
use std::convert::TryInto;
use std::marker::PhantomData;

#[derive(Debug, Clone)]
pub struct CreateCollectionBuilder<
'a,
OfferSet,
CollectionNameSet,
IndexingPolicySet,
PartitionKeySet,
> where
OfferSet: ToAssign,
CollectionNameSet: ToAssign,
IndexingPolicySet: ToAssign,
PartitionKeySet: ToAssign,
{
pub struct CreateCollectionBuilder<'a> {
partition_key: PartitionKey,
database_client: &'a DatabaseClient,
offer: Option<Offer>,
collection_name: Option<&'a str>,
indexing_policy: Option<&'a IndexingPolicy>,
partition_key: Option<PartitionKey>,
user_agent: Option<UserAgent<'a>>,
activity_id: Option<ActivityId<'a>>,
consistency_level: Option<ConsistencyLevel>,
p_offer: PhantomData<OfferSet>,
p_collection_name: PhantomData<CollectionNameSet>,
p_indexing_policy: PhantomData<IndexingPolicySet>,
p_partition_key: PhantomData<PartitionKeySet>,
indexing_policy: Option<IndexingPolicy>,
offer: Option<Offer>,
}

impl<'a> CreateCollectionBuilder<'a, No, No, No, No> {
pub(crate) fn new(database_client: &'a DatabaseClient) -> Self {
impl<'a> CreateCollectionBuilder<'a> {
pub(crate) fn new(database_client: &'a DatabaseClient, partition_key: PartitionKey) -> Self {
Self {
partition_key,
database_client,
offer: None,
collection_name: None,
indexing_policy: None,
partition_key: None,
user_agent: None,
activity_id: None,
consistency_level: None,
p_indexing_policy: PhantomData,
p_collection_name: PhantomData,
p_partition_key: PhantomData,
p_offer: PhantomData,
indexing_policy: None,
offer: None,
}
}
}

impl<'a, OfferSet, CollectionNameSet, IndexingPolicySet, PartitionKeySet>
CreateCollectionBuilder<'a, OfferSet, CollectionNameSet, IndexingPolicySet, PartitionKeySet>
where
OfferSet: ToAssign,
CollectionNameSet: ToAssign,
IndexingPolicySet: ToAssign,
PartitionKeySet: ToAssign,
{
impl<'a> CreateCollectionBuilder<'a> {
setters! {
user_agent: &'a str => Some(UserAgent::new(user_agent)),
activity_id: &'a str => Some(ActivityId::new(activity_id)),
consistency_level: ConsistencyLevel => Some(consistency_level),
indexing_policy: IndexingPolicy => Some(indexing_policy),
offer: Offer => Some(offer),
}
}

impl<'a, CollectionNameSet, IndexingPolicySet, PartitionKeySet>
CreateCollectionBuilder<'a, No, CollectionNameSet, IndexingPolicySet, PartitionKeySet>
where
CollectionNameSet: ToAssign,
IndexingPolicySet: ToAssign,
PartitionKeySet: ToAssign,
{
pub fn offer(
self,
offer: Offer,
) -> CreateCollectionBuilder<'a, Yes, CollectionNameSet, IndexingPolicySet, PartitionKeySet>
{
CreateCollectionBuilder {
offer: Some(offer),
database_client: self.database_client,
collection_name: self.collection_name,
indexing_policy: self.indexing_policy,
partition_key: self.partition_key,
user_agent: self.user_agent,
activity_id: self.activity_id,
consistency_level: self.consistency_level,
p_offer: PhantomData,
p_collection_name: PhantomData,
p_indexing_policy: PhantomData,
p_partition_key: PhantomData,
}
}
}

impl<'a, OfferSet, IndexingPolicySet, PartitionKeySet>
CreateCollectionBuilder<'a, OfferSet, No, IndexingPolicySet, PartitionKeySet>
where
OfferSet: ToAssign,
IndexingPolicySet: ToAssign,
PartitionKeySet: ToAssign,
{
pub fn collection_name(
self,
collection_name: &'a str,
) -> CreateCollectionBuilder<'a, OfferSet, Yes, IndexingPolicySet, PartitionKeySet> {
CreateCollectionBuilder {
collection_name: Some(collection_name),
database_client: self.database_client,
offer: self.offer,
indexing_policy: self.indexing_policy,
partition_key: self.partition_key,
user_agent: self.user_agent,
activity_id: self.activity_id,
consistency_level: self.consistency_level,
p_offer: PhantomData,
p_collection_name: PhantomData,
p_indexing_policy: PhantomData,
p_partition_key: PhantomData,
}
}
}

impl<'a, OfferSet, CollectionNameSet, PartitionKeySet>
CreateCollectionBuilder<'a, OfferSet, CollectionNameSet, No, PartitionKeySet>
where
OfferSet: ToAssign,
CollectionNameSet: ToAssign,
PartitionKeySet: ToAssign,
{
pub fn indexing_policy(
self,
indexing_policy: &'a IndexingPolicy,
) -> CreateCollectionBuilder<'a, OfferSet, CollectionNameSet, Yes, PartitionKeySet> {
CreateCollectionBuilder {
indexing_policy: Some(indexing_policy),
database_client: self.database_client,
offer: self.offer,
collection_name: self.collection_name,
partition_key: self.partition_key,
user_agent: self.user_agent,
activity_id: self.activity_id,
consistency_level: self.consistency_level,
p_offer: PhantomData,
p_collection_name: PhantomData,
p_indexing_policy: PhantomData,
p_partition_key: PhantomData,
}
}
}

impl<'a, OfferSet, CollectionNameSet, IndexingPolicySet>
CreateCollectionBuilder<'a, OfferSet, CollectionNameSet, IndexingPolicySet, No>
where
OfferSet: ToAssign,
CollectionNameSet: ToAssign,
IndexingPolicySet: ToAssign,
{
pub fn partition_key<P: Into<PartitionKey>>(
self,
partition_key: P,
) -> CreateCollectionBuilder<'a, OfferSet, CollectionNameSet, IndexingPolicySet, Yes> {
CreateCollectionBuilder {
partition_key: Some(partition_key.into()),
database_client: self.database_client,
offer: self.offer,
collection_name: self.collection_name,
indexing_policy: self.indexing_policy,
user_agent: self.user_agent,
activity_id: self.activity_id,
consistency_level: self.consistency_level,
p_offer: PhantomData,
p_collection_name: PhantomData,
p_indexing_policy: PhantomData,
p_partition_key: PhantomData,
}
}
}

impl<'a> CreateCollectionBuilder<'a, Yes, Yes, Yes, Yes> {
impl<'a> CreateCollectionBuilder<'a> {
// call this function to complete the builder
pub async fn execute(&self) -> Result<CreateCollectionResponse, CosmosError> {
pub async fn execute<C: AsRef<str>>(
&self,
collection_name: C,
) -> Result<CreateCollectionResponse, CosmosError> {
trace!("CreateCollectionBuilder::execute called");

let mut req = self.database_client.cosmos_client().prepare_request(
Expand All @@ -196,16 +58,16 @@ impl<'a> CreateCollectionBuilder<'a, Yes, Yes, Yes, Yes> {
req = req.header(http::header::CONTENT_TYPE, "application/json");

// add trait headers
let req = azure_core::headers::add_mandatory_header(&self.offer.unwrap(), req);
let req = azure_core::headers::add_optional_header(&self.offer, req);
let req = azure_core::headers::add_optional_header(&self.user_agent, req);
let req = azure_core::headers::add_optional_header(&self.activity_id, req);
let req = azure_core::headers::add_optional_header(&self.consistency_level, req);

let mut collection = Collection::new(
self.collection_name.unwrap(),
self.indexing_policy.unwrap().to_owned(),
);
collection.parition_key = self.partition_key.as_ref().unwrap().clone();
let collection = CreateCollectionBody {
id: collection_name.as_ref(),
indexing_policy: &self.indexing_policy,
partition_key: &self.partition_key,
};

let body = serde_json::to_string(&collection)?;
debug!("body == {}", body);
Expand All @@ -221,3 +83,13 @@ impl<'a> CreateCollectionBuilder<'a, Yes, Yes, Yes, Yes> {
.try_into()?)
}
}

/// Body for the create collection request
#[derive(Serialize, Debug)]
struct CreateCollectionBody<'a> {
pub id: &'a str,
#[serde(rename = "indexingPolicy", skip_serializing_if = "Option::is_none")]
pub indexing_policy: &'a Option<IndexingPolicy>,
#[serde(rename = "partitionKey")]
pub partition_key: &'a PartitionKey,
}
31 changes: 4 additions & 27 deletions sdk/cosmos/src/resources/collection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

mod offer;

pub use offer::Offer;

use super::Resource;
pub use offer::Offer;

/// A container of JSON documents and associated JavaScript application logic.
///
Expand Down Expand Up @@ -36,25 +35,6 @@ pub struct Collection {
pub conflicts: String,
}

impl Collection {
pub fn new(id: &str, indexing_policy: IndexingPolicy) -> Collection {
Collection {
id: id.to_owned(),
indexing_policy,
parition_key: PartitionKey::default(),
rid: String::new(),
ts: 0,
_self: String::new(),
etag: String::new(),
docs: String::new(),
sprocs: String::new(),
triggers: String::new(),
udfs: String::new(),
conflicts: String::new(),
}
}
}

impl Resource for Collection {
fn uri(&self) -> &str {
&self._self
Expand Down Expand Up @@ -112,7 +92,7 @@ pub struct ExcludedPath {
pub path: String,
}

impl std::convert::From<String> for ExcludedPath {
impl From<String> for ExcludedPath {
fn from(s: String) -> Self {
Self { path: s }
}
Expand All @@ -133,7 +113,7 @@ impl std::default::Default for PartitionKey {
}
}

impl<T> std::convert::From<T> for PartitionKey
impl<T> From<T> for PartitionKey
where
T: AsRef<str>,
{
Expand All @@ -146,13 +126,10 @@ where
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialOrd, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct IndexingPolicy {
#[serde(rename = "automatic")]
pub automatic: bool,
#[serde(rename = "indexingMode")]
pub indexing_mode: IndexingMode,
#[serde(rename = "includedPaths")]
pub included_paths: Vec<IncludedPath>,
#[serde(rename = "excludedPaths")]
pub excluded_paths: Vec<ExcludedPath>,
}
8 changes: 3 additions & 5 deletions sdk/cosmos/tests/attachment_00.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,10 @@ async fn attachment() -> Result<(), CosmosError> {
};

database_client
.create_collection()
.collection_name(&COLLECTION_NAME)
.partition_key("/id")
.create_collection("/id")
.offer(Offer::Throughput(400))
.indexing_policy(&ip)
.execute()
.indexing_policy(ip)
.execute(COLLECTION_NAME)
.await
.unwrap()
};
Expand Down
Loading