mirror of
https://github.com/hoytech/strfry.git
synced 2025-06-18 01:08:51 +00:00
initial commit
This commit is contained in:
207
src/RelayServer.h
Normal file
207
src/RelayServer.h
Normal file
@ -0,0 +1,207 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
#include <hoytech/timer.h>
|
||||
#include <hoytech/time.h>
|
||||
#include <hoytech/hex.h>
|
||||
#include <hoytech/file_change_monitor.h>
|
||||
#include <uWebSockets/src/uWS.h>
|
||||
#include <tao/json.hpp>
|
||||
#include <quadrable.h>
|
||||
|
||||
#include "golpe.h"
|
||||
|
||||
#include "Subscription.h"
|
||||
#include "ThreadPool.h"
|
||||
#include "events.h"
|
||||
#include "filters.h"
|
||||
#include "yesstr.h"
|
||||
|
||||
|
||||
|
||||
|
||||
struct MsgWebsocket : NonCopyable {
|
||||
struct Send {
|
||||
uint64_t connId;
|
||||
std::string payload;
|
||||
};
|
||||
|
||||
struct SendBinary {
|
||||
uint64_t connId;
|
||||
std::string payload;
|
||||
};
|
||||
|
||||
struct SendEventToBatch {
|
||||
RecipientList list;
|
||||
std::string evJson;
|
||||
};
|
||||
|
||||
using Var = std::variant<Send, SendBinary, SendEventToBatch>;
|
||||
Var msg;
|
||||
MsgWebsocket(Var &&msg_) : msg(std::move(msg_)) {}
|
||||
};
|
||||
|
||||
struct MsgIngester : NonCopyable {
|
||||
struct ClientMessage {
|
||||
uint64_t connId;
|
||||
std::string payload;
|
||||
};
|
||||
|
||||
struct CloseConn {
|
||||
uint64_t connId;
|
||||
};
|
||||
|
||||
using Var = std::variant<ClientMessage, CloseConn>;
|
||||
Var msg;
|
||||
MsgIngester(Var &&msg_) : msg(std::move(msg_)) {}
|
||||
};
|
||||
|
||||
struct MsgWriter : NonCopyable {
|
||||
struct AddEvent {
|
||||
uint64_t connId;
|
||||
uint64_t receivedAt;
|
||||
std::string flatStr;
|
||||
std::string jsonStr;
|
||||
};
|
||||
|
||||
using Var = std::variant<AddEvent>;
|
||||
Var msg;
|
||||
MsgWriter(Var &&msg_) : msg(std::move(msg_)) {}
|
||||
};
|
||||
|
||||
struct MsgReqWorker : NonCopyable {
|
||||
struct NewSub {
|
||||
Subscription sub;
|
||||
};
|
||||
|
||||
struct RemoveSub {
|
||||
uint64_t connId;
|
||||
SubId subId;
|
||||
};
|
||||
|
||||
struct CloseConn {
|
||||
uint64_t connId;
|
||||
};
|
||||
|
||||
using Var = std::variant<NewSub, RemoveSub, CloseConn>;
|
||||
Var msg;
|
||||
MsgReqWorker(Var &&msg_) : msg(std::move(msg_)) {}
|
||||
};
|
||||
|
||||
struct MsgReqMonitor : NonCopyable {
|
||||
struct NewSub {
|
||||
Subscription sub;
|
||||
};
|
||||
|
||||
struct RemoveSub {
|
||||
uint64_t connId;
|
||||
SubId subId;
|
||||
};
|
||||
|
||||
struct CloseConn {
|
||||
uint64_t connId;
|
||||
};
|
||||
|
||||
struct DBChange {
|
||||
};
|
||||
|
||||
using Var = std::variant<NewSub, RemoveSub, CloseConn, DBChange>;
|
||||
Var msg;
|
||||
MsgReqMonitor(Var &&msg_) : msg(std::move(msg_)) {}
|
||||
};
|
||||
|
||||
struct MsgYesstr : NonCopyable {
|
||||
struct SyncRequest {
|
||||
uint64_t connId;
|
||||
std::string yesstrMessage;
|
||||
};
|
||||
|
||||
struct CloseConn {
|
||||
uint64_t connId;
|
||||
};
|
||||
|
||||
using Var = std::variant<SyncRequest, CloseConn>;
|
||||
Var msg;
|
||||
MsgYesstr(Var &&msg_) : msg(std::move(msg_)) {}
|
||||
};
|
||||
|
||||
|
||||
struct RelayServer {
|
||||
std::unique_ptr<uS::Async> hubTrigger;
|
||||
|
||||
// Thread Pools
|
||||
|
||||
ThreadPool<MsgWebsocket> tpWebsocket;
|
||||
ThreadPool<MsgIngester> tpIngester;
|
||||
ThreadPool<MsgWriter> tpWriter;
|
||||
ThreadPool<MsgReqWorker> tpReqWorker;
|
||||
ThreadPool<MsgReqMonitor> tpReqMonitor;
|
||||
ThreadPool<MsgYesstr> tpYesstr;
|
||||
hoytech::timer cron;
|
||||
|
||||
void run();
|
||||
|
||||
void runWebsocket(ThreadPool<MsgWebsocket>::Thread &thr);
|
||||
|
||||
void runIngester(ThreadPool<MsgIngester>::Thread &thr);
|
||||
void ingesterProcessEvent(lmdb::txn &txn, uint64_t connId, secp256k1_context *secpCtx, const tao::json::value &origJson, std::vector<MsgWriter> &output);
|
||||
void ingesterProcessReq(lmdb::txn &txn, uint64_t connId, const tao::json::value &origJson);
|
||||
void ingesterProcessClose(lmdb::txn &txn, uint64_t connId, const tao::json::value &origJson);
|
||||
|
||||
void runWriter(ThreadPool<MsgWriter>::Thread &thr);
|
||||
|
||||
void runReqWorker(ThreadPool<MsgReqWorker>::Thread &thr);
|
||||
|
||||
void runReqMonitor(ThreadPool<MsgReqMonitor>::Thread &thr);
|
||||
|
||||
void runYesstr(ThreadPool<MsgYesstr>::Thread &thr);
|
||||
|
||||
void cleanupOldEvents();
|
||||
|
||||
// Utils (can be called by any thread)
|
||||
|
||||
void sendToConn(uint64_t connId, std::string &&payload) {
|
||||
tpWebsocket.dispatch(0, MsgWebsocket{MsgWebsocket::Send{connId, std::move(payload)}});
|
||||
hubTrigger->send();
|
||||
}
|
||||
|
||||
void sendToConn(uint64_t connId, std::string &payload) {
|
||||
tpWebsocket.dispatch(0, MsgWebsocket{MsgWebsocket::Send{connId, std::move(payload)}});
|
||||
hubTrigger->send();
|
||||
}
|
||||
|
||||
void sendToConnBinary(uint64_t connId, std::string &&payload) {
|
||||
tpWebsocket.dispatch(0, MsgWebsocket{MsgWebsocket::SendBinary{connId, std::move(payload)}});
|
||||
hubTrigger->send();
|
||||
}
|
||||
|
||||
void sendEvent(uint64_t connId, const SubId &subId, std::string_view evJson) {
|
||||
std::string reply = std::string("[\"EVENT\",\"");
|
||||
reply += subId.sv();
|
||||
reply += "\",";
|
||||
reply += evJson;
|
||||
reply += "]";
|
||||
sendToConn(connId, reply);
|
||||
}
|
||||
|
||||
void sendEventToBatch(RecipientList &&list, std::string &&evJson) {
|
||||
tpWebsocket.dispatch(0, MsgWebsocket{MsgWebsocket::SendEventToBatch{std::move(list), std::move(evJson)}});
|
||||
hubTrigger->send();
|
||||
}
|
||||
|
||||
void sendNoticeError(uint64_t connId, std::string &&payload) {
|
||||
LI << "sending error to [" << connId << "]: " << payload;
|
||||
auto reply = tao::json::value::array({ "NOTICE", std::string("ERROR: ") + payload });
|
||||
tpWebsocket.dispatch(0, MsgWebsocket{MsgWebsocket::Send{connId, std::move(tao::json::to_string(reply))}});
|
||||
hubTrigger->send();
|
||||
}
|
||||
|
||||
void sendOKResponse(uint64_t connId, std::string_view eventIdHex, bool written, std::string_view message) {
|
||||
auto reply = tao::json::value::array({ "OK", eventIdHex, written, message });
|
||||
tpWebsocket.dispatch(0, MsgWebsocket{MsgWebsocket::Send{connId, std::move(tao::json::to_string(reply))}});
|
||||
hubTrigger->send();
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user