Skip to content

Commit 1d7c5a0

Browse files
author
Sicheng Pan
committed
Wire up server
1 parent 5ecb617 commit 1d7c5a0

File tree

2 files changed

+75
-3
lines changed

2 files changed

+75
-3
lines changed

Diff for: rust/frontend/src/auth/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ pub enum AuthzAction {
2121
CreateCollection,
2222
GetOrCreateCollection,
2323
GetCollection,
24-
DeleteCollection,
2524
UpdateCollection,
25+
DeleteCollection,
26+
ForkCollection,
2627
Add,
2728
Delete,
2829
Get,
@@ -47,8 +48,9 @@ impl Display for AuthzAction {
4748
AuthzAction::CreateCollection => write!(f, "db:create_collection"),
4849
AuthzAction::GetOrCreateCollection => write!(f, "db:get_or_create_collection"),
4950
AuthzAction::GetCollection => write!(f, "collection:get_collection"),
50-
AuthzAction::DeleteCollection => write!(f, "collection:delete_collection"),
5151
AuthzAction::UpdateCollection => write!(f, "collection:update_collection"),
52+
AuthzAction::DeleteCollection => write!(f, "collection:delete_collection"),
53+
AuthzAction::ForkCollection => write!(f, "collection:fork_collection"),
5254
AuthzAction::Add => write!(f, "collection:add"),
5355
AuthzAction::Delete => write!(f, "collection:delete"),
5456
AuthzAction::Get => write!(f, "collection:get"),

Diff for: rust/frontend/src/server.rs

+71-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use axum::{
66
Json, Router, ServiceExt,
77
};
88
use chroma_system::System;
9-
use chroma_types::RawWhereFields;
109
use chroma_types::{
1110
AddCollectionRecordsResponse, ChecklistResponse, Collection, CollectionConfiguration,
1211
CollectionMetadataUpdate, CollectionUuid, CountCollectionsRequest, CountCollectionsResponse,
@@ -20,6 +19,7 @@ use chroma_types::{
2019
UpdateCollectionConfiguration, UpdateCollectionRecordsResponse, UpdateCollectionResponse,
2120
UpdateMetadata, UpsertCollectionRecordsResponse,
2221
};
22+
use chroma_types::{ForkCollectionResponse, RawWhereFields};
2323
use mdac::{Rule, Scorecard, ScorecardTicket};
2424
use opentelemetry::global;
2525
use opentelemetry::metrics::{Counter, Meter};
@@ -93,6 +93,7 @@ pub struct Metrics {
9393
get_collection: Counter<u64>,
9494
update_collection: Counter<u64>,
9595
delete_collection: Counter<u64>,
96+
fork_collection: Counter<u64>,
9697
collection_add: Counter<u64>,
9798
collection_update: Counter<u64>,
9899
collection_upsert: Counter<u64>,
@@ -123,6 +124,7 @@ impl Metrics {
123124
get_collection: meter.u64_counter("get_collection").build(),
124125
update_collection: meter.u64_counter("update_collection").build(),
125126
delete_collection: meter.u64_counter("delete_collection").build(),
127+
fork_collection: meter.u64_counter("fork_collection").build(),
126128
collection_add: meter.u64_counter("collection_add").build(),
127129
collection_update: meter.u64_counter("collection_update").build(),
128130
collection_upsert: meter.u64_counter("collection_upsert").build(),
@@ -232,6 +234,10 @@ impl FrontendServer {
232234
.put(update_collection)
233235
.delete(delete_collection),
234236
)
237+
.route(
238+
"/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/fork",
239+
post(fork_collection),
240+
)
235241
.route(
236242
"/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/add",
237243
post(collection_add),
@@ -1090,6 +1096,70 @@ async fn delete_collection(
10901096
Ok(Json(UpdateCollectionResponse {}))
10911097
}
10921098

1099+
#[derive(Deserialize, Serialize, ToSchema, Debug, Clone)]
1100+
pub struct ForkCollectionPayload {
1101+
pub new_name: String,
1102+
}
1103+
1104+
/// Forks an existing collection.
1105+
#[utoipa::path(
1106+
post,
1107+
path = "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/fork",
1108+
request_body = ForkCollectionPayload,
1109+
responses(
1110+
(status = 200, description = "Collection forked successfully", body = ForkCollectionResponse),
1111+
(status = 401, description = "Unauthorized", body = ErrorResponse),
1112+
(status = 404, description = "Collection not found", body = ErrorResponse),
1113+
(status = 500, description = "Server error", body = ErrorResponse)
1114+
),
1115+
params(
1116+
("tenant" = String, Path, description = "Tenant ID"),
1117+
("database" = String, Path, description = "Database name"),
1118+
("collection_id" = String, Path, description = "UUID of the collection to update")
1119+
)
1120+
)]
1121+
async fn fork_collection(
1122+
headers: HeaderMap,
1123+
Path((tenant, database, collection_id)): Path<(String, String, String)>,
1124+
State(mut server): State<FrontendServer>,
1125+
Json(payload): Json<ForkCollectionPayload>,
1126+
) -> Result<Json<ForkCollectionResponse>, ServerError> {
1127+
server.metrics.fork_collection.add(
1128+
1,
1129+
&[
1130+
KeyValue::new("tenant", tenant.clone()),
1131+
KeyValue::new("collection_id", collection_id.clone()),
1132+
],
1133+
);
1134+
tracing::info!(
1135+
"Forking collection [{collection_id}] in database [{database}] for tenant [{tenant}]"
1136+
);
1137+
server
1138+
.authenticate_and_authorize(
1139+
&headers,
1140+
AuthzAction::ForkCollection,
1141+
AuthzResource {
1142+
tenant: Some(tenant.clone()),
1143+
database: Some(database.clone()),
1144+
collection: Some(collection_id.clone()),
1145+
},
1146+
)
1147+
.await?;
1148+
let _guard =
1149+
server.scorecard_request(&["op:fork_collection", format!("tenant:{}", tenant).as_str()]);
1150+
let collection_id =
1151+
CollectionUuid::from_str(&collection_id).map_err(|_| ValidationError::CollectionId)?;
1152+
1153+
let request = chroma_types::ForkCollectionRequest::try_new(
1154+
tenant,
1155+
database,
1156+
collection_id,
1157+
payload.new_name,
1158+
)?;
1159+
1160+
Ok(Json(server.frontend.fork_collection(request).await?))
1161+
}
1162+
10931163
#[derive(Serialize, Deserialize, ToSchema, Debug, Clone)]
10941164
pub struct AddCollectionRecordsPayload {
10951165
ids: Vec<String>,

0 commit comments

Comments
 (0)