| 459 | } |
| 460 | |
| 461 | Status Module::__call_reducer__( |
| 462 | uint32_t id, |
| 463 | uint64_t sender_0, uint64_t sender_1, uint64_t sender_2, uint64_t sender_3, |
| 464 | uint64_t conn_id_0, uint64_t conn_id_1, |
| 465 | Timestamp timestamp, |
| 466 | BytesSource args_source, |
| 467 | BytesSink error_sink |
| 468 | ) { |
| 469 | // Clear any previous error state |
| 470 | SpacetimeDB::Internal::clear_reducer_error(); |
| 471 | |
| 472 | // Check if reducer ID is valid |
| 473 | if (id >= g_reducer_handlers.size()) { |
| 474 | fprintf(stderr, "ERROR: Invalid reducer ID %u (have %zu reducers)\n", |
| 475 | id, g_reducer_handlers.size()); |
| 476 | |
| 477 | // Write error message |
| 478 | std::string error = "Invalid reducer ID: " + std::to_string(id); |
| 479 | WriteBytes(error_sink, std::vector<uint8_t>(error.begin(), error.end())); |
| 480 | return StatusCode::NO_SUCH_REDUCER; |
| 481 | } |
| 482 | |
| 483 | // Create reducer context |
| 484 | std::array<uint8_t, 32> sender_bytes{}; |
| 485 | // Pack the 4 uint64_t parts into 32 bytes |
| 486 | std::memcpy(sender_bytes.data(), &sender_0, 8); |
| 487 | std::memcpy(sender_bytes.data() + 8, &sender_1, 8); |
| 488 | std::memcpy(sender_bytes.data() + 16, &sender_2, 8); |
| 489 | std::memcpy(sender_bytes.data() + 24, &sender_3, 8); |
| 490 | |
| 491 | Identity sender_identity(sender_bytes); |
| 492 | |
| 493 | // Create connection ID if provided |
| 494 | std::optional<ConnectionId> connection_id; |
| 495 | if (conn_id_0 != 0 || conn_id_1 != 0) { |
| 496 | // ConnectionId is 128-bit (two 64-bit parts) |
| 497 | connection_id = ConnectionId(u128(conn_id_1, conn_id_0)); |
| 498 | } |
| 499 | |
| 500 | ReducerContext ctx(sender_identity, connection_id, timestamp); |
| 501 | |
| 502 | // Get the handler |
| 503 | const auto& handler_info = g_reducer_handlers[id]; |
| 504 | |
| 505 | // Call the reducer handler |
| 506 | handler_info.handler(ctx, args_source); |
| 507 | |
| 508 | // Check if the reducer failed gracefully |
| 509 | if (SpacetimeDB::Internal::has_reducer_error()) { |
| 510 | std::string error_msg = SpacetimeDB::Internal::get_reducer_error(); |
| 511 | WriteBytes(error_sink, std::vector<uint8_t>(error_msg.begin(), error_msg.end())); |
| 512 | return StatusCode::HOST_CALL_FAILURE; |
| 513 | } |
| 514 | |
| 515 | return StatusCode::OK; |
| 516 | } |
| 517 | |
| 518 | // Dispatch function for views with ViewContext (has sender) |
nothing calls this directly
no test coverage detected