diff --git a/services/backup/docker-server/contents/server/src/Errors/EndConnectionError.h b/services/backup/docker-server/contents/server/src/Errors/EndConnectionError.h new file mode 100644 --- /dev/null +++ b/services/backup/docker-server/contents/server/src/Errors/EndConnectionError.h @@ -0,0 +1,13 @@ +#pragma once + +namespace comm { +namespace network { + +struct EndConnectionError : public std::exception { + const char *what() const throw() { + return "connection ended"; + } +}; + +} // namespace network +} // namespace comm 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,62 @@ +#pragma once + +#include +#include + +#include "EndConnectionError.h" + +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) { + if (this->finished) { + return; + } + this->finished = true; + this->Finish(status); + } + +public: + ReactorBase() { + this->StartRead(&this->request); + } + + void OnDone() override { + GPR_ASSERT(this->finished); + delete this; + } + + void OnReadDone(bool ok) override { + if (!ok) { + this->finish(); + return; + } + try { + this->response = this->handleRequest(this->request); + this->StartWrite(&this->response); + } catch (EndConnectionError &e) { + this->finish(); + } catch (std::runtime_error &e) { + this->finish(grpc::Status(grpc::StatusCode::INTERNAL, e.what())); + } + } + + void OnWriteDone(bool ok) override { + if (!ok) { + gpr_log(GPR_ERROR, "Server write failed"); + return; + } + this->StartRead(&this->request); + } + + virtual Response handleRequest(Request request) = 0; +}; + +} // namespace network +} // namespace comm