Skip to content

Commit b6216a2

Browse files
author
Sicheng Pan
committed
Wire up server
1 parent e5adf6d commit b6216a2

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
UpdateCollectionRecordsResponse, UpdateCollectionResponse, UpdateMetadata,
2120
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),
@@ -1088,6 +1094,70 @@ async fn delete_collection(
10881094
Ok(Json(UpdateCollectionResponse {}))
10891095
}
10901096

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

0 commit comments

Comments
 (0)