(
store: &Store,
route_name: &str,
provider_name: &str,
model_id: &str,
timeout_secs: u64,
verify: bool,
)
| 154 | } |
| 155 | |
| 156 | async fn upsert_cluster_inference_route( |
| 157 | store: &Store, |
| 158 | route_name: &str, |
| 159 | provider_name: &str, |
| 160 | model_id: &str, |
| 161 | timeout_secs: u64, |
| 162 | verify: bool, |
| 163 | ) -> Result<UpsertedInferenceRoute, Status> { |
| 164 | if provider_name.trim().is_empty() { |
| 165 | return Err(Status::invalid_argument("provider_name is required")); |
| 166 | } |
| 167 | if model_id.trim().is_empty() { |
| 168 | return Err(Status::invalid_argument("model_id is required")); |
| 169 | } |
| 170 | |
| 171 | let provider = store |
| 172 | .get_message_by_name::<Provider>(provider_name) |
| 173 | .await |
| 174 | .map_err(|e| Status::internal(format!("fetch provider failed: {e}")))? |
| 175 | .ok_or_else(|| { |
| 176 | Status::failed_precondition(format!("provider '{provider_name}' not found")) |
| 177 | })?; |
| 178 | |
| 179 | let resolved = resolve_provider_route(&provider, model_id)?; |
| 180 | let validation = if verify { |
| 181 | vec![verify_provider_endpoint(provider.object_name(), model_id, &resolved).await?] |
| 182 | } else { |
| 183 | Vec::new() |
| 184 | }; |
| 185 | |
| 186 | let config = build_cluster_inference_config(&provider, model_id, timeout_secs); |
| 187 | |
| 188 | // Fetch existing route to determine create vs. update path |
| 189 | let existing = store |
| 190 | .get_message_by_name::<InferenceRoute>(route_name) |
| 191 | .await |
| 192 | .map_err(|e| Status::internal(format!("fetch route failed: {e}")))?; |
| 193 | |
| 194 | let now_ms = current_time_ms(); |
| 195 | |
| 196 | let (id, metadata, new_version, condition) = if let Some(existing) = existing { |
| 197 | // Update path: preserve metadata, increment version, use CAS |
| 198 | let resource_version = existing.metadata.as_ref().map_or(0, |m| m.resource_version); |
| 199 | ( |
| 200 | existing.object_id().to_string(), |
| 201 | existing.metadata.clone(), |
| 202 | existing.version.saturating_add(1), |
| 203 | WriteCondition::MatchResourceVersion(resource_version), |
| 204 | ) |
| 205 | } else { |
| 206 | // Create path: new metadata, version 1, use MustCreate |
| 207 | let new_id = uuid::Uuid::new_v4().to_string(); |
| 208 | let new_metadata = Some(openshell_core::proto::datamodel::v1::ObjectMeta { |
| 209 | id: new_id.clone(), |
| 210 | name: route_name.to_string(), |
| 211 | created_at_ms: now_ms, |
| 212 | labels: std::collections::HashMap::new(), |
| 213 | resource_version: 0, |
no test coverage detected