diff --git a/services/backup/docker-server/contents/server/src/ReactorBase.h b/services/backup/docker-server/contents/server/src/ReactorBase.h new file mode 100644 --- /dev/null +++ b/services/backup/docker-server/contents/server/src/ReactorBase.h @@ -0,0 +1,79 @@ +#pragma once + +#include +#include + +namespace comm { +namespace network { + +template +class ReactorBase : public grpc::ServerBidiReactor { + Request request; + Response response; + bool finished = false; + + void finish(grpc::Status status = grpc::Status::OK); + +public: + ReactorBase(); + + void OnDone() override; + void OnReadDone(bool ok) override; + void OnWriteDone(bool ok) override; + + virtual grpc::Status handleRequest(Request request, Response *response) = 0; +}; + +template +void ReactorBase::finish(grpc::Status status) { + if (this->finished) { + return; + } + this->finished = true; + this->Finish(status); +} + +template +ReactorBase::ReactorBase() { + this->StartRead(&this->request); +} + +template +void ReactorBase::OnDone() { + if (!this->finished) { + throw std::runtime_error( + "trying to delete the reactor without finishing the connection " + "properly"); + } + delete this; +} + +template +void ReactorBase::OnReadDone(bool ok) { + if (!ok) { + this->finish(grpc::Status(grpc::StatusCode::INTERNAL, "reading error")); + return; + } + try { + grpc::Status status = this->handleRequest(this->request, &this->response); + if (status.ok()) { + this->finish(status); + return; + } + this->StartWrite(&this->response); + } catch (std::runtime_error &e) { + this->finish(grpc::Status(grpc::StatusCode::INTERNAL, e.what())); + } +} + +template +void ReactorBase::OnWriteDone(bool ok) { + if (!ok) { + gpr_log(GPR_ERROR, "Server write failed"); + return; + } + this->StartRead(&this->request); +} + +} // namespace network +} // namespace comm