···
82
82
}
83
83
84
84
#[derive(Debug, Deserialize, JsonSchema)]
85
85
-
struct CollectionQuery {
85
85
+
struct CollectionsQuery {
86
86
collection: String, // JsonSchema not implemented for Nsid :(
87
87
+
}
88
88
+
impl CollectionsQuery {
89
89
+
fn to_multiple_nsids(&self) -> Result<Vec<Nsid>, String> {
90
90
+
let mut out = Vec::with_capacity(self.collection.len());
91
91
+
for collection in self.collection.split(',') {
92
92
+
let Ok(nsid) = Nsid::new(collection.to_string()) else {
93
93
+
return Err(format!("collection {collection:?} was not a valid NSID"));
94
94
+
};
95
95
+
out.push(nsid);
96
96
+
}
97
97
+
Ok(out)
98
98
+
}
87
99
}
88
100
#[derive(Debug, Serialize, JsonSchema)]
89
101
struct ApiRecord {
···
111
123
}
112
124
}
113
125
/// Get recent records by collection
126
126
+
///
127
127
+
/// Multiple collections are supported. they will be delivered in one big array with no
128
128
+
/// specified order.
114
129
#[endpoint {
115
130
method = GET,
116
131
path = "/records",
117
132
}]
118
133
async fn get_records_by_collection(
119
134
ctx: RequestContext<Context>,
120
120
-
collection_query: Query<CollectionQuery>,
135
135
+
collection_query: Query<CollectionsQuery>,
121
136
) -> OkCorsResponse<Vec<ApiRecord>> {
122
122
-
let Ok(collection) = Nsid::new(collection_query.into_inner().collection) else {
123
123
-
return Err(HttpError::for_bad_request(
124
124
-
None,
125
125
-
"collection must be an NSID".to_string(),
126
126
-
));
127
127
-
};
128
137
let Context { storage, .. } = ctx.context();
129
129
-
let records = storage
130
130
-
.get_collection_records(&collection, 100)
131
131
-
.await
132
132
-
.map_err(|e| HttpError::for_internal_error(e.to_string()))?;
138
138
+
139
139
+
let collections = collection_query
140
140
+
.into_inner()
141
141
+
.to_multiple_nsids()
142
142
+
.map_err(|reason| HttpError::for_bad_request(None, reason))?;
133
143
134
134
-
if records.is_empty() {
135
135
-
return Err(HttpError::for_not_found(
136
136
-
None,
137
137
-
format!("no saved records for collection {collection:?}"),
138
138
-
));
144
144
+
let mut api_records = Vec::new();
145
145
+
146
146
+
// TODO: set up multiple db iterators and iterate them together with merge sort
147
147
+
for collection in &collections {
148
148
+
let records = storage
149
149
+
.get_collection_records(collection, 100)
150
150
+
.await
151
151
+
.map_err(|e| HttpError::for_internal_error(e.to_string()))?;
152
152
+
153
153
+
for record in records {
154
154
+
let api_record = ApiRecord::from_create_record(record, collection);
155
155
+
api_records.push(api_record);
156
156
+
}
139
157
}
140
158
141
141
-
let api_records = records
142
142
-
.into_iter()
143
143
-
.map(|r| ApiRecord::from_create_record(r, &collection))
144
144
-
.collect();
145
145
-
146
159
ok_cors(api_records)
147
160
}
148
161
···
153
166
}]
154
167
async fn get_records_total_seen(
155
168
ctx: RequestContext<Context>,
156
156
-
collection_query: Query<CollectionQuery>,
157
157
-
) -> OkCorsResponse<u64> {
158
158
-
let Ok(collection) = Nsid::new(collection_query.into_inner().collection) else {
159
159
-
return Err(HttpError::for_bad_request(
160
160
-
None,
161
161
-
"collection must be an NSID".to_string(),
162
162
-
));
163
163
-
};
169
169
+
collection_query: Query<CollectionsQuery>,
170
170
+
) -> OkCorsResponse<HashMap<String, u64>> {
164
171
let Context { storage, .. } = ctx.context();
165
165
-
let total = storage
166
166
-
.get_collection_total_seen(&collection)
167
167
-
.await
168
168
-
.map_err(|e| HttpError::for_internal_error(format!("boooo: {e:?}")))?;
172
172
+
173
173
+
let collections = collection_query
174
174
+
.into_inner()
175
175
+
.to_multiple_nsids()
176
176
+
.map_err(|reason| HttpError::for_bad_request(None, reason))?;
169
177
170
170
-
ok_cors(total)
178
178
+
let mut seen_by_collection = HashMap::with_capacity(collections.len());
179
179
+
180
180
+
for collection in &collections {
181
181
+
let total = storage
182
182
+
.get_collection_total_seen(collection)
183
183
+
.await
184
184
+
.map_err(|e| HttpError::for_internal_error(format!("boooo: {e:?}")))?;
185
185
+
186
186
+
seen_by_collection.insert(collection.to_string(), total);
187
187
+
}
188
188
+
189
189
+
ok_cors(seen_by_collection)
171
190
}
172
191
173
192
/// Get top collections