1use serde::{Deserialize, Serialize};
2use std::time::SystemTime;
3
4use crate::CollectionUuid;
5
6fn prost_value_to_json(v: &prost_types::Value) -> serde_json::Value {
7 match &v.kind {
8 Some(prost_types::value::Kind::NullValue(_)) => serde_json::Value::Null,
9 Some(prost_types::value::Kind::NumberValue(n)) => serde_json::json!(*n),
10 Some(prost_types::value::Kind::StringValue(s)) => serde_json::Value::String(s.clone()),
11 Some(prost_types::value::Kind::BoolValue(b)) => serde_json::Value::Bool(*b),
12 Some(prost_types::value::Kind::StructValue(s)) => prost_struct_to_json(s),
13 Some(prost_types::value::Kind::ListValue(l)) => {
14 serde_json::Value::Array(l.values.iter().map(prost_value_to_json).collect())
15 }
16 None => serde_json::Value::Null,
17 }
18}
19
20fn prost_struct_to_json(s: &prost_types::Struct) -> serde_json::Value {
21 let map: serde_json::Map<String, serde_json::Value> = s
22 .fields
23 .iter()
24 .map(|(k, v)| (k.clone(), prost_value_to_json(v)))
25 .collect();
26 serde_json::Value::Object(map)
27}
28
29define_uuid_newtype!(
30 JobId,
33 new_v4
34);
35
36impl From<CollectionUuid> for JobId {
38 fn from(collection_uuid: CollectionUuid) -> Self {
39 JobId(collection_uuid.0)
40 }
41}
42
43impl From<AttachedFunctionUuid> for JobId {
44 fn from(attached_function_uuid: AttachedFunctionUuid) -> Self {
45 JobId(attached_function_uuid.0)
46 }
47}
48
49define_uuid_newtype!(
50 #[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
52 AttachedFunctionUuid,
53 new_v4
54);
55
56fn default_systemtime() -> SystemTime {
59 SystemTime::UNIX_EPOCH
60}
61
62#[derive(Clone, Debug, Deserialize, Serialize)]
63pub struct AttachedFunction {
64 pub id: AttachedFunctionUuid,
66 pub name: String,
68 pub function_id: uuid::Uuid,
70 pub input_collection_id: CollectionUuid,
72 pub output_collection_name: String,
74 pub output_collection_id: Option<CollectionUuid>,
76 pub params: Option<String>,
78 pub tenant_id: String,
80 pub database_id: String,
82 #[serde(skip, default)]
84 pub last_run: Option<SystemTime>,
85 pub completion_offset: u64,
87 pub min_records_for_invocation: u64,
89 #[serde(skip, default)]
91 pub is_deleted: bool,
92 #[serde(skip, default)]
94 pub is_async: bool,
95 #[serde(default = "default_systemtime")]
97 pub created_at: SystemTime,
98 #[serde(default = "default_systemtime")]
100 pub updated_at: SystemTime,
101 }
105
106#[derive(Debug, thiserror::Error)]
107pub enum AttachedFunctionConversionError {
108 #[error("Invalid UUID: {0}")]
109 InvalidUuid(String),
110}
111
112impl TryFrom<crate::chroma_proto::AttachedFunction> for AttachedFunction {
113 type Error = AttachedFunctionConversionError;
114
115 fn try_from(
116 attached_function: crate::chroma_proto::AttachedFunction,
117 ) -> Result<Self, Self::Error> {
118 let attached_function_id = attached_function
120 .id
121 .parse::<AttachedFunctionUuid>()
122 .map_err(|_| {
123 AttachedFunctionConversionError::InvalidUuid("attached_function_id".to_string())
124 })?;
125
126 let function_id = attached_function
128 .function_id
129 .parse::<uuid::Uuid>()
130 .map_err(|_| AttachedFunctionConversionError::InvalidUuid("function_id".to_string()))?;
131
132 let input_collection_id = attached_function
134 .input_collection_id
135 .parse::<CollectionUuid>()
136 .map_err(|_| {
137 AttachedFunctionConversionError::InvalidUuid("input_collection_id".to_string())
138 })?;
139
140 let output_collection_id = attached_function
142 .output_collection_id
143 .map(|id| id.parse::<CollectionUuid>())
144 .transpose()
145 .map_err(|_| {
146 AttachedFunctionConversionError::InvalidUuid("output_collection_id".to_string())
147 })?;
148
149 let params = attached_function
150 .params
151 .as_ref()
152 .map(|s| serde_json::to_string(&prost_struct_to_json(s)))
153 .transpose()
154 .unwrap_or(None);
155
156 let created_at = std::time::SystemTime::UNIX_EPOCH
158 + std::time::Duration::from_micros(attached_function.created_at);
159 let updated_at = std::time::SystemTime::UNIX_EPOCH
160 + std::time::Duration::from_micros(attached_function.updated_at);
161
162 Ok(AttachedFunction {
163 id: attached_function_id,
164 name: attached_function.name,
165 function_id,
166 input_collection_id,
167 output_collection_name: attached_function.output_collection_name,
168 output_collection_id,
169 params,
170 tenant_id: attached_function.tenant_id,
171 database_id: attached_function.database_id,
172 last_run: None, completion_offset: attached_function.completion_offset,
174 min_records_for_invocation: attached_function.min_records_for_invocation,
175 is_deleted: false, is_async: attached_function.is_async,
177 created_at,
178 updated_at,
179 })
180 }
181}