factor IPC out of server RPC

This commit is contained in:
Сергей Маринкевич
2025-12-03 18:27:08 +07:00
parent 00d359a064
commit 43f67275e2
6 changed files with 130 additions and 46 deletions
+61
View File
@@ -0,0 +1,61 @@
#pragma once
#include <ipc/IpcMessage.h>
#include <rpc/RpcValue.h>
#include <string>
// Кодек, который знает, как упаковать/распаковать RPC-запросы/ответы
// в/IpcMessage. Живёт в IPC-слое, но опирается на типы RPC-ядра
// (RpcValue/RpcArgs).
namespace IpcCodec {
// Запрос: имя метода + вектор аргументов.
inline IpcMessage encodeRequest(const std::string& method,
const RpcArgs& args) {
IpcMessage msg;
// имя метода
msg.add(method);
// аргументы (PoC: только int)
for (const auto& a : args) {
msg.add(a.asInt());
}
return msg;
}
inline void decodeRequest(const IpcMessage& msg,
std::string& method,
RpcArgs& args) {
IpcMessage copy = msg;
// имя метода
method = copy.get<std::string>();
// аргументы (PoC: только int, читаем до конца сообщения)
args.clear();
while (!copy.empty()) {
int v = copy.get<int>();
args.emplace_back(RpcValue::fromInt(v));
}
}
// Ответ: одно RpcValue (PoC: считаем, что это int).
inline IpcMessage encodeResponse(const RpcValue& result) {
IpcMessage msg;
msg.add(result.asInt()); // PoC: только int
return msg;
}
inline RpcValue decodeResponse(const IpcMessage& msg) {
IpcMessage copy = msg;
int v = copy.get<int>();
return RpcValue::fromInt(v);
}
} // namespace IpcCodec
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include <ipc/IpcChannel.h>
#include <ipc/IpcCodec.h>
#include <rpc/RpcInvoker.h>
#include <string>
// Серверный диспетчер, который получает IpcMessage с канала,
// декодирует его в RPC-вызов, вызывает RpcInvoker и шлёт ответ.
class IpcDispatcher {
public:
IpcDispatcher(IpcChannel& ch, RpcInvoker& invoker)
: channel_(ch)
, invoker_(invoker) {}
// Обработать один запрос. Возвращает false, если получили "пустое"
// сообщение и цикл стоит завершить.
bool handleOnce() {
IpcMessage req = channel_.receive();
if (req.empty()) {
return false;
}
std::string method;
RpcArgs args;
IpcCodec::decodeRequest(req, method, args);
RpcValue result = invoker_.dispatch(method, args);
IpcMessage resp = IpcCodec::encodeResponse(result);
channel_.send(resp);
return true;
}
// Простой цикл обработки до тех пор, пока канал не вернёт пустое сообщение.
void loop() {
while (handleOnce()) {
}
}
private:
IpcChannel& channel_;
RpcInvoker& invoker_;
};
+5 -11
View File
@@ -1,6 +1,7 @@
#pragma once
#include <ipc/IpcChannel.h>
#include <ipc/IpcCodec.h>
#include <rpc/RpcValue.h>
class ProxyMarshaller {
@@ -9,22 +10,15 @@ public:
// Базовый type-erased вызов: принимает вектор RpcValue и возвращает RpcValue.
RpcValue call(const std::string& method, const RpcArgs& args) {
IpcMessage msg;
// имя метода
msg.add(method);
// аргументы (PoC: только int)
for (const auto& a : args) {
msg.add(a.asInt());
}
// упаковать запрос в IpcMessage
IpcMessage msg = IpcCodec::encodeRequest(method, args);
// отправить
channel.send(msg);
// получить ответ
// получить ответ и распаковать
IpcMessage resp = channel.receive();
return RpcValue::fromInt(resp.get<int>());
return IpcCodec::decodeResponse(resp);
}
// Удобный шаблонный хелпер для сгенерированных прокси.