Skip to content

feat etcd: Init etcd client #837

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 44 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
145a211
init etcd client
eskedesu Jan 16, 2025
b184754
minor fixes
eskedesu Jan 16, 2025
bf56139
iteration
eskedesu Jan 20, 2025
3c1e377
rename client
eskedesu Jan 20, 2025
fc3f6e7
iteration
eskedesu Feb 1, 2025
a1119f6
iteration
eskedesu Feb 2, 2025
330ef41
iteration
eskedesu Feb 16, 2025
dfcee7d
iteration
eskedesu Feb 16, 2025
327f1fc
iteration
eskedesu Mar 2, 2025
54c585b
iteration
eskedesu Mar 16, 2025
00b6bb8
iteration
eskedesu Mar 16, 2025
497666d
iteration
eskedesu Mar 16, 2025
dc8b0f9
iteration
eskedesu Apr 16, 2025
636ef6b
iteration
eskedesu May 2, 2025
79818cc
remove connection timeout change
eskedesu May 2, 2025
c83160a
remove allowed url prefix
eskedesu May 2, 2025
4207ee2
fix config plugin
eskedesu May 2, 2025
ae04fb6
format
eskedesu May 3, 2025
9903913
fix doc
eskedesu May 3, 2025
40ce833
Merge branch 'userver-framework:develop' into init_etcd_client
eskedesu May 4, 2025
7c571f3
add tests
eskedesu May 4, 2025
6e1993f
add tests
eskedesu May 4, 2025
5ab0eab
add watch test
eskedesu May 5, 2025
ba964f7
delete file
eskedesu May 7, 2025
e9c866c
iteration
eskedesu May 9, 2025
fe9b745
format
eskedesu May 9, 2025
b8f4a82
iteration
eskedesu May 9, 2025
2d02e27
iteration
eskedesu May 10, 2025
2ff2c8a
iteration
eskedesu May 10, 2025
83f325c
fix namespaces
eskedesu May 10, 2025
6a7d901
Merge branch 'userver-framework:develop' into init_etcd_client
eskedesu May 10, 2025
8d5c5d4
iteration
eskedesu May 10, 2025
3f896d8
format
eskedesu May 14, 2025
a2f72a4
Add retries for watch
eskedesu May 15, 2025
2d2ef4b
fix WatchListener
eskedesu May 15, 2025
81b7f32
add chaotic
eskedesu May 15, 2025
1870b81
iteration
eskedesu May 15, 2025
d664db7
fix convertion
eskedesu May 16, 2025
645a253
fix convertion
eskedesu May 16, 2025
c2c8657
fix namespace
eskedesu May 16, 2025
195dc37
fix namespaces for string64
eskedesu May 16, 2025
df6fc8c
add throws tag
eskedesu May 16, 2025
da9adcb
switch to BackgroundTaskStorage
eskedesu May 16, 2025
f4b316a
fix logs
eskedesu May 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
"chaotic/include/userver/chaotic/dynamic_config_variable_bundle.hpp":"taxi/uservices/userver/chaotic/include/userver/chaotic/dynamic_config_variable_bundle.hpp",
"chaotic/include/userver/chaotic/exception.hpp":"taxi/uservices/userver/chaotic/include/userver/chaotic/exception.hpp",
"chaotic/include/userver/chaotic/io/boost/uuids/uuid.hpp":"taxi/uservices/userver/chaotic/include/userver/chaotic/io/boost/uuids/uuid.hpp",
"chaotic/include/userver/chaotic/io/crypto/base64/string64.hpp":"taxi/uservices/userver/chaotic/include/userver/chaotic/io/crypto/base64/string64.hpp",
"chaotic/include/userver/chaotic/io/userver/crypto/base64/string64.hpp":"taxi/uservices/userver/chaotic/include/userver/chaotic/io/crypto/base64/string64.hpp",
"chaotic/include/userver/chaotic/io/decimal64/decimal.hpp":"taxi/uservices/userver/chaotic/include/userver/chaotic/io/decimal64/decimal.hpp",
"chaotic/include/userver/chaotic/io/std/chrono/days.hpp":"taxi/uservices/userver/chaotic/include/userver/chaotic/io/std/chrono/days.hpp",
"chaotic/include/userver/chaotic/io/std/chrono/duration.hpp":"taxi/uservices/userver/chaotic/include/userver/chaotic/io/std/chrono/duration.hpp",
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ option(USERVER_FEATURE_MYSQL "Provide asynchronous driver for MariaDB/MySQL" "${
option(USERVER_FEATURE_ROCKS "Provide asynchronous driver for Rocks" "${USERVER_LIB_ENABLED_DEFAULT}")
option(USERVER_FEATURE_YDB "Provide asynchronous driver for YDB" "${USERVER_YDB_DEFAULT}")
option(USERVER_FEATURE_OTLP "Provide asynchronous OTLP exporters" "${USERVER_LIB_ENABLED_DEFAULT}")
option(USERVER_FEATURE_ETCD "Provide asynchronous driver for etcd" "${USERVER_LIB_ENABLED_DEFAULT}")

set(CMAKE_DEBUG_POSTFIX d)

Expand Down Expand Up @@ -298,6 +299,11 @@ if (USERVER_FEATURE_YDB)
list(APPEND USERVER_AVAILABLE_COMPONENTS ydb)
endif()

if (USERVER_FEATURE_ETCD)
_require_userver_core("USERVER_FEATURE_ETCD")
add_subdirectory(etcd)
endif()

add_subdirectory(libraries)

if (USERVER_BUILD_TESTS)
Expand Down
2 changes: 1 addition & 1 deletion chaotic/chaotic/back/cpp/translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ def _gen_string(

if schema.format:
if schema.format == types.StringFormat.BYTE:
format_cpp_type = 'crypto::base64::String64'
format_cpp_type = 'userver::crypto::base64::String64'
elif schema.format == types.StringFormat.UUID:
format_cpp_type = 'boost::uuids::uuid'
elif schema.format == types.StringFormat.DATE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include <string>

USERVER_NAMESPACE_BEGIN

namespace crypto::base64 {

// RFC4648
Expand All @@ -14,8 +16,6 @@ class String64 : public USERVER_NAMESPACE::utils::StrongTypedef<String64, std::s

} // namespace crypto::base64

USERVER_NAMESPACE_BEGIN

namespace chaotic::convert {

crypto::base64::String64 Convert(const std::string& str, chaotic::convert::To<crypto::base64::String64>);
Expand Down
8 changes: 4 additions & 4 deletions chaotic/src/chaotic/io/crypto/base64/string64.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
#include <userver/chaotic/io/crypto/base64/string64.hpp>
#include <userver/chaotic/io/userver/crypto/base64/string64.hpp>

#include <userver/crypto/base64.hpp>

USERVER_NAMESPACE_BEGIN

namespace chaotic::convert {

::crypto::base64::String64 Convert(const std::string& str, chaotic::convert::To<::crypto::base64::String64>) {
return ::crypto::base64::String64(crypto::base64::Base64Decode(str));
crypto::base64::String64 Convert(const std::string& str, chaotic::convert::To<crypto::base64::String64>) {
return crypto::base64::String64(crypto::base64::Base64Decode(str));
}

std::string Convert(const ::crypto::base64::String64& str64, chaotic::convert::To<std::string>) {
std::string Convert(const crypto::base64::String64& str64, chaotic::convert::To<std::string>) {
return crypto::base64::Base64Encode(str64.GetUnderlying());
}

Expand Down
19 changes: 19 additions & 0 deletions chaotic/src/chaotic/io/userver/crypto/base64/string64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <userver/chaotic/io/userver/crypto/base64/string64.hpp>

#include <userver/crypto/base64.hpp>

USERVER_NAMESPACE_BEGIN

namespace chaotic::convert {

crypto::base64::String64 Convert(const std::string& str, chaotic::convert::To<crypto::base64::String64>) {
return crypto::base64::String64(crypto::base64::Base64Decode(str));
}

std::string Convert(const crypto::base64::String64& str64, chaotic::convert::To<std::string>) {
return crypto::base64::Base64Encode(str64.GetUnderlying());
}

} // namespace chaotic::convert

USERVER_NAMESPACE_END
2 changes: 1 addition & 1 deletion chaotic/tests/back/cpp/test_tr_string.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def test_byte(simple_gen):
assert types == {
'::type': cpp_types.CppStringWithFormat(
raw_cpp_type=type_name.TypeName('std::string'),
format_cpp_type='crypto::base64::String64',
format_cpp_type='userver::crypto::base64::String64',
user_cpp_type=None,
json_schema=None,
nullable=False,
Expand Down
11 changes: 11 additions & 0 deletions cmake/install/userver-etcd-config.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
include_guard(GLOBAL)

if(userver_etcd_FOUND)
return()
endif()

find_package(userver REQUIRED COMPONENTS
core
)

set(userver_etcd_FOUND TRUE)
24 changes: 24 additions & 0 deletions etcd/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
project(userver-etcd CXX)

file(GLOB_RECURSE SCHEMAS ${CMAKE_CURRENT_SOURCE_DIR}/schemas/*.yaml)
userver_target_generate_chaotic(${PROJECT_NAME}-chgen
GENERATE_SERIALIZERS
LAYOUT
"/components/schemas/([^/]*)/=etcd_schemas::{0}"
OUTPUT_DIR
${CMAKE_CURRENT_BINARY_DIR}/src
SCHEMAS
${SCHEMAS}
RELATIVE_TO
${CMAKE_CURRENT_SOURCE_DIR}
)

userver_module(etcd
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
UTEST_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*_test.cpp"
LINK_LIBRARIES ${PROJECT_NAME}-chgen
)

if (USERVER_BUILD_TESTS)
add_subdirectory(functional_tests)
endif()
6 changes: 6 additions & 0 deletions etcd/functional_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
project(userver-etcd-tests CXX)

add_custom_target(${PROJECT_NAME})

add_subdirectory(client)
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-client)
6 changes: 6 additions & 0 deletions etcd/functional_tests/client/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
project(userver-etcd-tests-client CXX)

add_executable(${PROJECT_NAME} "etcd_service.cpp")
target_link_libraries(${PROJECT_NAME} userver-core userver-etcd)

userver_chaos_testsuite_add()
92 changes: 92 additions & 0 deletions etcd/functional_tests/client/etcd_service.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include <userver/utest/using_namespace_userver.hpp>

#include <fmt/format.h>

#include <userver/clients/dns/component.hpp>
#include <userver/clients/http/component.hpp>
#include <userver/components/component_list.hpp>
#include <userver/components/minimal_server_component_list.hpp>
#include <userver/etcd/component.hpp>
#include <userver/server/handlers/http_handler_base.hpp>
#include <userver/server/handlers/ping.hpp>
#include <userver/server/handlers/tests_control.hpp>
#include <userver/testsuite/testsuite_support.hpp>
#include <userver/utils/daemon_run.hpp>

namespace {

class HandlerV1Get final : public server::handlers::HttpHandlerBase {
public:
static constexpr std::string_view kName = "handler-v1-get";

HandlerV1Get(const components::ComponentConfig& config, const components::ComponentContext& component_context)
: HttpHandlerBase(config, component_context),
etcd_client_ptr_(component_context.FindComponent<etcd::Component>("etcd-client").GetClient()) {}

std::string HandleRequestThrow(const server::http::HttpRequest& request, server::request::RequestContext&)
const override {
const auto maybe_value = etcd_client_ptr_->Get(request.GetArg("key"));
return maybe_value.value_or("No value");
}

private:
etcd::ClientPtr etcd_client_ptr_;
};

class HandlerV1Put final : public server::handlers::HttpHandlerBase {
public:
static constexpr std::string_view kName = "handler-v1-put";

HandlerV1Put(const components::ComponentConfig& config, const components::ComponentContext& component_context)
: HttpHandlerBase(config, component_context),
etcd_client_ptr_(component_context.FindComponent<etcd::Component>("etcd-client").GetClient()) {}

std::string HandleRequestThrow(const server::http::HttpRequest& request, server::request::RequestContext&)
const override {
etcd_client_ptr_->Put(request.GetArg("key"), request.GetArg("value"));

return std::string();
}

private:
etcd::ClientPtr etcd_client_ptr_;
};

class HandlerV1Watch final : public server::handlers::HttpHandlerBase {
public:
static constexpr std::string_view kName = "handler-v1-watch";

HandlerV1Watch(const components::ComponentConfig& config, const components::ComponentContext& component_context)
: HttpHandlerBase(config, component_context),
etcd_client_ptr_(component_context.FindComponent<etcd::Component>("etcd-client").GetClient()) {}

std::string HandleRequestThrow(const server::http::HttpRequest& request, server::request::RequestContext&)
const override {
const auto key = request.GetArg("key");
const auto maybe_original_value = etcd_client_ptr_->Get(key);
auto watch_listener = etcd_client_ptr_->StartWatch(key);
const auto watch_event = watch_listener.GetEvent();
const auto new_value = watch_event.value;
return fmt::format("original value: {}, new value: {}", maybe_original_value.value_or("No value"), new_value);
}

private:
etcd::ClientPtr etcd_client_ptr_;
};

} // namespace

int main(int argc, char* argv[]) {
auto component_list = components::MinimalServerComponentList()
.Append<server::handlers::Ping>()
.Append<components::TestsuiteSupport>()
.Append<components::HttpClient>()
.Append<clients::dns::Component>()
.Append<etcd::Component>()
.Append<server::handlers::TestsControl>()
.Append<HandlerV1Get>()
.Append<HandlerV1Put>()
.Append<HandlerV1Watch>();

return utils::DaemonMain(argc, argv, component_list);
}
76 changes: 76 additions & 0 deletions etcd/functional_tests/client/static_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# yaml
components_manager:
task_processors:
main-task-processor:
worker_threads: 4

fs-task-processor:
worker_threads: 1

default_task_processor: main-task-processor

components:
server:
listener:
port: 8080
task_processor: main-task-processor
connection:
http-version: '2'
http2-session:
max_concurrent_streams: 100
max_frame_size: 16384
initial_window_size: 65536
listener-monitor:
port: 8081
task_processor: main-task-processor
logging:
fs-task-processor: fs-task-processor
loggers:
default:
file_path: '@stderr'
level: error
overflow_behavior: discard

http-client:
fs-task-processor: fs-task-processor
user-agent: $server-name
user-agent#fallback: 'userver-based-service 1.0'
dns-client:
fs-task-processor: fs-task-processor
testsuite-support:
tests-control:
path: /tests/{action}
method: POST
task_processor: main-task-processor
testpoint-timeout: 10s
testpoint-url: $mockserver/testpoint
throttling_enabled: false

handler-ping:
path: /ping
method: GET
task_processor: main-task-processor
throttling_enabled: false
url_trailing_slash: strict-match

etcd-client:
endpoints:
- http://localhost:2379
attempts: 2
request_timeout_ms: 500
watch_timeout_ms: 1000000

handler-v1-get:
path: /v1/get
method: POST
task_processor: main-task-processor

handler-v1-put:
path: /v1/put
method: PUT
task_processor: main-task-processor

handler-v1-watch:
path: /v1/watch
method: POST
task_processor: main-task-processor
Loading