Call a reducer or procedure on the specified database module.
(
State(worker_ctx): State<S>,
Extension(auth): Extension<SpacetimeAuth>,
Path(CallParams {
name_or_identity,
reducer,
}): Path<CallParams>,
TypedHeader(content_typ
| 137 | |
| 138 | /// Call a reducer or procedure on the specified database module. |
| 139 | pub async fn call<S: ControlStateDelegate + NodeDelegate>( |
| 140 | State(worker_ctx): State<S>, |
| 141 | Extension(auth): Extension<SpacetimeAuth>, |
| 142 | Path(CallParams { |
| 143 | name_or_identity, |
| 144 | reducer, |
| 145 | }): Path<CallParams>, |
| 146 | TypedHeader(content_type): TypedHeader<headers::ContentType>, |
| 147 | ByteStringBody(body): ByteStringBody, |
| 148 | ) -> axum::response::Result<impl IntoResponse> { |
| 149 | assert_content_type_json(content_type)?; |
| 150 | |
| 151 | let caller_identity = auth.claims.identity; |
| 152 | |
| 153 | let args = FunctionArgs::Json(body); |
| 154 | |
| 155 | // HTTP callers always need a connection ID to provide to connect/disconnect, |
| 156 | // so generate one. |
| 157 | let connection_id = generate_random_connection_id(); |
| 158 | |
| 159 | let (module, Database { owner_identity, .. }) = find_module_and_database(&worker_ctx, name_or_identity).await?; |
| 160 | |
| 161 | // Call the database's `client_connected` reducer, if any. |
| 162 | // If it fails or rejects the connection, bail. |
| 163 | module |
| 164 | .call_identity_connected(auth.into(), connection_id) |
| 165 | .await |
| 166 | .map_err(client_connected_error_to_response)?; |
| 167 | |
| 168 | let result = match module |
| 169 | .call_reducer( |
| 170 | caller_identity, |
| 171 | Some(connection_id), |
| 172 | None, |
| 173 | None, |
| 174 | None, |
| 175 | &reducer, |
| 176 | args.clone(), |
| 177 | ) |
| 178 | .await |
| 179 | { |
| 180 | Ok(rcr) => Ok(CallResult::Reducer(rcr)), |
| 181 | Err(ReducerCallError::NoSuchReducer | ReducerCallError::ScheduleReducerNotFound) => { |
| 182 | // Not a reducer — try procedure instead |
| 183 | match module |
| 184 | .call_procedure(caller_identity, Some(connection_id), None, &reducer, args) |
| 185 | .await |
| 186 | .result |
| 187 | { |
| 188 | Ok(res) => Ok(CallResult::Procedure(res)), |
| 189 | Err(e) => Err(map_procedure_error(e, &reducer)), |
| 190 | } |
| 191 | } |
| 192 | Err(e) => Err(map_reducer_error(e, &reducer)), |
| 193 | }; |
| 194 | |
| 195 | module |
| 196 | .call_identity_disconnected(caller_identity, connection_id) |
searching dependent graphs…