Skip to content

Commit 6adb2bc

Browse files
author
Sicheng Pan
committed
Wire up server
1 parent 2496b45 commit 6adb2bc

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};
@@ -103,6 +103,7 @@ pub struct Metrics {
103103
get_collection: Counter<u64>,
104104
update_collection: Counter<u64>,
105105
delete_collection: Counter<u64>,
106+
fork_collection: Counter<u64>,
106107
collection_add: Counter<u64>,
107108
collection_update: Counter<u64>,
108109
collection_upsert: Counter<u64>,
@@ -133,6 +134,7 @@ impl Metrics {
133134
get_collection: meter.u64_counter("get_collection").build(),
134135
update_collection: meter.u64_counter("update_collection").build(),
135136
delete_collection: meter.u64_counter("delete_collection").build(),
137+
fork_collection: meter.u64_counter("fork_collection").build(),
136138
collection_add: meter.u64_counter("collection_add").build(),
137139
collection_update: meter.u64_counter("collection_update").build(),
138140
collection_upsert: meter.u64_counter("collection_upsert").build(),
@@ -242,6 +244,10 @@ impl FrontendServer {
242244
.put(update_collection)
243245
.delete(delete_collection),
244246
)
247+
.route(
248+
"/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/fork",
249+
post(fork_collection),
250+
)
245251
.route(
246252
"/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/add",
247253
post(collection_add),
@@ -1106,6 +1112,70 @@ async fn delete_collection(
11061112
Ok(Json(UpdateCollectionResponse {}))
11071113
}
11081114

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

0 commit comments

Comments
 (0)