/
bonekeE
/
sbt_distributed_systems_lab_3
Обзор
Документация
Войти
/
bonekeE
/
sbt_distributed_systems_lab_3
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
main.cpp
166 строк
6 KB
Your Name
add lab3
19 май 2025, 12:03
19 май 2025, 12:03
f9631af
Код
Авторство
О чём код?
#include <userver/clients/dns/component.hpp> #include <userver/testsuite/testsuite_support.hpp> #include <userver/utest/using_namespace_userver.hpp> /// [Postgres service sample - component] #include <userver/components/component.hpp> #include <userver/components/minimal_server_component_list.hpp> #include <userver/server/handlers/http_handler_base.hpp> #include <userver/utils/daemon_run.hpp> #include <userver/storages/postgres/cluster.hpp> #include <userver/storages/postgres/component.hpp> #include <samples_postgres_service/sql_queries.hpp> constexpr size_t number_of_db_ = 2; namespace samples_postgres_service::pg { class KeyValue final : public server::handlers::HttpHandlerBase { public: static constexpr std::string_view kName = "handler-key-value"; KeyValue(const components::ComponentConfig& config, const components::ComponentContext& context); std::string HandleRequest(server::http::HttpRequest& request, server::request::RequestContext&) const override; private: std::string GetValue(std::string_view key, const server::http::HttpRequest& request) const; std::string PostValue(std::string_view key, const server::http::HttpRequest& request) const; std::string DeleteValue(std::string_view key) const; std::vector<storages::postgres::ClusterPtr> pg_clusters_; size_t get_db_index(std::string_view key) const { return std::hash<std::string_view>()(key) % number_of_db_; } }; } // namespace samples_postgres_service::pg /// [Postgres service sample - component] namespace samples_postgres_service::pg { /// [Postgres service sample - component constructor] KeyValue::KeyValue(const components::ComponentConfig& config, const components::ComponentContext& context) : HttpHandlerBase(config, context) { using storages::postgres::ClusterHostType; for(size_t i = 0; i < number_of_db_; i++) { pg_clusters_.emplace_back(context.FindComponent<components::Postgres> ("key-value-database-" + std::to_string(i)).GetCluster()); pg_clusters_[i]->Execute(ClusterHostType::kMaster, sql::kCreateTable); } } /// [Postgres service sample - component constructor] /// [Postgres service sample - HandleRequestThrow] std::string KeyValue::HandleRequest(server::http::HttpRequest& request, server::request::RequestContext&) const { const auto& key = request.GetArg("key"); if (key.empty()) { throw server::handlers::ClientError(server::handlers::ExternalBody{"No 'key' query argument"}); } size_t db_index = get_db_index(key); request.GetHttpResponse().SetContentType(http::content_type::kTextPlain); std::string respond; switch (request.GetMethod()) { case server::http::HttpMethod::kGet: respond = GetValue(key, request); break; case server::http::HttpMethod::kPost: respond = PostValue(key, request); break; case server::http::HttpMethod::kDelete: respond = DeleteValue(key); break; default: throw server::handlers::ClientError(server::handlers::ExternalBody{ fmt::format("Unsupported method {}", request.GetMethod())}); } return fmt::format("respond = {}, db_index = {}\n", respond, db_index); } /// [Postgres service sample - HandleRequestThrow] /// [Postgres service sample - GetValue] const storages::postgres::Query kSelectValue{ "SELECT value FROM key_value_table WHERE key=$1", storages::postgres::Query::Name{"sample_select_value"}, }; std::string KeyValue::GetValue(std::string_view key, const server::http::HttpRequest& request) const { storages::postgres::ResultSet res = pg_clusters_[get_db_index(key)]->Execute(storages::postgres::ClusterHostType::kSlave, kSelectValue, key); if (res.IsEmpty()) { request.SetResponseStatus(server::http::HttpStatus::kNotFound); return {}; } return res.AsSingleRow<std::string>(); } /// [Postgres service sample - GetValue] /// [Postgres service sample - PostValue] const storages::postgres::Query kInsertValue{ "INSERT INTO key_value_table (key, value) " "VALUES ($1, $2) " "ON CONFLICT DO NOTHING", storages::postgres::Query::Name{"sample_insert_value"}, }; std::string KeyValue::PostValue(std::string_view key, const server::http::HttpRequest& request) const { const auto& value = request.GetArg("value"); storages::postgres::Transaction transaction = pg_clusters_[get_db_index(key)]->Begin("sample_transaction_insert_key_value", storages::postgres::ClusterHostType::kMaster, {}); auto res = transaction.Execute(kInsertValue, key, value); if (res.RowsAffected()) { transaction.Commit(); request.SetResponseStatus(server::http::HttpStatus::kCreated); return std::string{value}; } res = transaction.Execute(kSelectValue, key); transaction.Rollback(); auto result = res.AsSingleRow<std::string>(); if (result != value) { request.SetResponseStatus(server::http::HttpStatus::kConflict); } return res.AsSingleRow<std::string>(); } /// [Postgres service sample - PostValue] /// [Postgres service sample - DeleteValue] std::string KeyValue::DeleteValue(std::string_view key) const { auto res = pg_clusters_[get_db_index(key)]->Execute( storages::postgres::ClusterHostType::kMaster, "DELETE FROM key_value_table WHERE key=$1", key ); return std::to_string(res.RowsAffected()); } /// [Postgres service sample - DeleteValue] } // namespace samples_postgres_service::pg /// [Postgres service sample - main] int main(int argc, char* argv[]) { const auto component_list = components::MinimalServerComponentList() .Append<samples_postgres_service::pg::KeyValue>() .Append<components::Postgres>("key-value-database-0") .Append<components::Postgres>("key-value-database-1") .Append<components::TestsuiteSupport>() .Append<clients::dns::Component>(); // for (size_t i = 0; i < number_of_db_; i++) { // component_list..Append<components::Postgres>("key-value-database-" + std::to_string(i)) // } return utils::DaemonMain(argc, argv, component_list); } /// [Postgres service sample - main]