|
1 | 1 | /// Inter-Database Communication (IDC) Runtime |
2 | 2 | /// |
3 | 3 | /// Background tokio task that: |
4 | | -/// 1. Loads undelivered entries from `st_msg_id` on startup, resolving delivery data from outbox tables. |
| 4 | +/// 1. Loads undelivered entries from `st_outbound_msg` on startup, resolving delivery data from outbox tables. |
5 | 5 | /// 2. Accepts immediate notifications via an mpsc channel when new outbox rows are inserted. |
6 | 6 | /// 3. Delivers each message in msg_id order via HTTP POST to |
7 | 7 | /// `http://localhost:80/v1/database/{target_db}/call-from-database/{reducer}?sender_identity=<hex>&msg_id=<n>` |
8 | 8 | /// 4. On transport errors (network, 5xx, 4xx except 422/402): retries infinitely with exponential |
9 | 9 | /// backoff, blocking only the affected target database (other targets continue unaffected). |
10 | 10 | /// 5. On reducer errors (HTTP 422) or budget exceeded (HTTP 402): calls the configured |
11 | | -/// `on_result_reducer` (read from the outbox table's schema) and deletes the st_msg_id row. |
| 11 | +/// `on_result_reducer` (read from the outbox table's schema) and deletes the st_outbound_msg row. |
12 | 12 | /// 6. Enforces sequential delivery per target database: msg N+1 is only delivered after N is done. |
13 | 13 | use crate::db::relational_db::RelationalDB; |
14 | 14 | use crate::host::module_host::WeakModuleHost; |
15 | 15 | use crate::host::FunctionArgs; |
16 | 16 | use spacetimedb_datastore::execution_context::Workload; |
17 | | -use spacetimedb_datastore::system_tables::{StMsgIdRow, ST_MSG_ID_ID}; |
| 17 | +use spacetimedb_datastore::system_tables::{StOutboundMsgRow, ST_OUTBOUND_MSG_ID}; |
18 | 18 | use spacetimedb_datastore::traits::IsolationLevel; |
19 | 19 | use spacetimedb_lib::{AlgebraicValue, Identity}; |
20 | 20 | use spacetimedb_primitives::{ColId, TableId}; |
@@ -207,19 +207,19 @@ async fn run_idc_loop( |
207 | 207 |
|
208 | 208 | /// Decode the delivery outcome into `(result_status, result_payload)` for recording. |
209 | 209 | fn outcome_to_result(outcome: &DeliveryOutcome) -> (u8, String) { |
210 | | - use spacetimedb_datastore::system_tables::st_inbound_msg_id_result_status; |
| 210 | + use spacetimedb_datastore::system_tables::st_inbound_msg_result_status; |
211 | 211 | match outcome { |
212 | | - DeliveryOutcome::Success => (st_inbound_msg_id_result_status::SUCCESS, String::new()), |
213 | | - DeliveryOutcome::ReducerError(msg) => (st_inbound_msg_id_result_status::REDUCER_ERROR, msg.clone()), |
| 212 | + DeliveryOutcome::Success => (st_inbound_msg_result_status::SUCCESS, String::new()), |
| 213 | + DeliveryOutcome::ReducerError(msg) => (st_inbound_msg_result_status::REDUCER_ERROR, msg.clone()), |
214 | 214 | DeliveryOutcome::BudgetExceeded => ( |
215 | | - st_inbound_msg_id_result_status::REDUCER_ERROR, |
| 215 | + st_inbound_msg_result_status::REDUCER_ERROR, |
216 | 216 | "budget exceeded".to_string(), |
217 | 217 | ), |
218 | 218 | DeliveryOutcome::TransportError(_) => unreachable!("transport errors never finalize"), |
219 | 219 | } |
220 | 220 | } |
221 | 221 |
|
222 | | -/// Finalize a delivered message: call the on_result reducer (if any), then delete from ST_MSG_ID. |
| 222 | +/// Finalize a delivered message: call the on_result reducer (if any), then delete from ST_OUTBOUND_MSG. |
223 | 223 | async fn finalize_message( |
224 | 224 | db: &RelationalDB, |
225 | 225 | module_host: &WeakModuleHost, |
@@ -288,25 +288,28 @@ async fn finalize_message( |
288 | 288 | delete_message(db, msg.msg_id); |
289 | 289 | } |
290 | 290 |
|
291 | | -/// Load all messages from ST_MSG_ID into the per-target queues, resolving delivery data |
| 291 | +/// Load all messages from ST_OUTBOUND_MSG into the per-target queues, resolving delivery data |
292 | 292 | /// from the corresponding outbox table rows. |
293 | 293 | /// |
294 | | -/// A row's presence in ST_MSG_ID means it has not yet been processed. |
| 294 | +/// A row's presence in ST_OUTBOUND_MSG means it has not yet been processed. |
295 | 295 | /// Messages already in a target's queue (by msg_id) are not re-added. |
296 | 296 | fn load_pending_into_targets(db: &RelationalDB, targets: &mut HashMap<Identity, TargetState>) { |
297 | 297 | let tx = db.begin_tx(Workload::Internal); |
298 | 298 |
|
299 | | - let st_msg_id_rows: Vec<StMsgIdRow> = db |
300 | | - .iter(&tx, ST_MSG_ID_ID) |
301 | | - .map(|iter| iter.filter_map(|row_ref| StMsgIdRow::try_from(row_ref).ok()).collect()) |
| 299 | + let st_outbound_msg_rows: Vec<StOutboundMsgRow> = db |
| 300 | + .iter(&tx, ST_OUTBOUND_MSG_ID) |
| 301 | + .map(|iter| { |
| 302 | + iter.filter_map(|row_ref| StOutboundMsgRow::try_from(row_ref).ok()) |
| 303 | + .collect() |
| 304 | + }) |
302 | 305 | .unwrap_or_else(|e| { |
303 | | - log::error!("idc_runtime: failed to read st_msg_id: {e}"); |
| 306 | + log::error!("idc_runtime: failed to read st_outbound_msg: {e}"); |
304 | 307 | Vec::new() |
305 | 308 | }); |
306 | 309 |
|
307 | | - let mut pending: Vec<PendingMessage> = Vec::with_capacity(st_msg_id_rows.len()); |
| 310 | + let mut pending: Vec<PendingMessage> = Vec::with_capacity(st_outbound_msg_rows.len()); |
308 | 311 |
|
309 | | - for st_row in st_msg_id_rows { |
| 312 | + for st_row in st_outbound_msg_rows { |
310 | 313 | let outbox_table_id = TableId(st_row.outbox_table_id); |
311 | 314 |
|
312 | 315 | // Read the outbox table schema for reducer name and on_result_reducer. |
@@ -432,10 +435,10 @@ async fn attempt_delivery( |
432 | 435 | } |
433 | 436 | } |
434 | 437 |
|
435 | | -/// Delete a message from ST_MSG_ID within a new transaction. |
| 438 | +/// Delete a message from ST_OUTBOUND_MSG within a new transaction. |
436 | 439 | fn delete_message(db: &RelationalDB, msg_id: u64) { |
437 | 440 | let mut tx = db.begin_mut_tx(IsolationLevel::Serializable, Workload::Internal); |
438 | | - if let Err(e) = tx.delete_msg_id(msg_id) { |
| 441 | + if let Err(e) = tx.delete_outbound_msg(msg_id) { |
439 | 442 | log::error!("idc_runtime: failed to delete msg_id={msg_id}: {e}"); |
440 | 443 | let _ = db.rollback_mut_tx(tx); |
441 | 444 | return; |
|
0 commit comments