Files
cvmmap-streamer/include/cvmmap_streamer/protocol/nats_request_reply_server.hpp
T
crosstyan 213adee887 feat: add streamer-owned recording control service
Introduce a dedicated streamer-side recording control plane instead of sharing the producer recorder API.

- register streamer-owned recorder endpoints as a NATS micro service
- add explicit MP4 and MCAP recorder control protobufs and subject helpers
- wire recorder lifecycle handling into the pipeline runtime
- add MP4 writer and depth-alignment support files used by the new recording flow
2026-04-12 20:22:28 +08:00

94 lines
2.3 KiB
C++

#pragma once
#include "proto/cvmmap_streamer/recorder_control.pb.h"
#include <cstdint>
#include <expected>
#include <functional>
#include <memory>
#include <span>
#include <string>
namespace cvmmap_streamer::protocol {
enum class RpcErrorCode : std::uint8_t {
InvalidRequest,
Unsupported,
Busy,
Internal,
};
struct RpcError {
RpcErrorCode code{RpcErrorCode::Internal};
std::string message{};
};
struct NatsRequestReplyServerOptions {
std::string nats_url{};
std::string instance_name{};
std::string namespace_name{};
std::string ipc_prefix{};
std::string base_name{};
std::string nats_target_key{};
std::string backend{"cvmmap-streamer"};
std::string recording_formats{};
};
class NatsRequestReplyServer {
public:
explicit NatsRequestReplyServer(NatsRequestReplyServerOptions options);
~NatsRequestReplyServer();
NatsRequestReplyServer(const NatsRequestReplyServer &) = delete;
NatsRequestReplyServer &operator=(const NatsRequestReplyServer &) = delete;
template <class Request, class Response>
void register_proto_endpoint(
std::string endpoint_name,
std::string subject,
std::function<std::expected<Response, RpcError>(const Request &)> handler) {
register_raw_endpoint(
std::move(endpoint_name),
std::move(subject),
[handler = std::move(handler)](std::span<const std::uint8_t> payload) {
Request request;
Response response;
if (!request.ParseFromArray(
payload.data(),
static_cast<int>(payload.size()))) {
response.set_code(cvmmap_streamer::proto::RPC_CODE_INVALID_REQUEST);
response.set_error_message("failed to parse protobuf request");
return response.SerializeAsString();
}
auto handled = handler(request);
if (!handled) {
response.set_code(to_proto_rpc_code(handled.error().code));
response.set_error_message(handled.error().message);
return response.SerializeAsString();
}
return handled->SerializeAsString();
});
}
[[nodiscard]]
bool start();
void stop();
private:
struct Endpoint;
struct Impl;
void register_raw_endpoint(
std::string endpoint_name,
std::string subject,
std::function<std::string(std::span<const std::uint8_t>)> handler);
static cvmmap_streamer::proto::RpcCode to_proto_rpc_code(RpcErrorCode code);
std::unique_ptr<Impl> impl_;
};
} // namespace cvmmap_streamer::protocol