Skip to content

Commit 54b56fc

Browse files
committed
cc server: prepare for early open of the monitor port
commit_hash:ec57f61c61be51b43f831f7c80bd460284c2de4f
1 parent 154d288 commit 54b56fc

18 files changed

+336
-84
lines changed

.mapping.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,11 @@
704704
"core/functional_tests/dynamic_configs/tests_kill_switches/test_disabled_kill_switch.py":"taxi/uservices/userver/core/functional_tests/dynamic_configs/tests_kill_switches/test_disabled_kill_switch.py",
705705
"core/functional_tests/dynamic_configs/tests_kill_switches/test_enabled_kill_switch.py":"taxi/uservices/userver/core/functional_tests/dynamic_configs/tests_kill_switches/test_enabled_kill_switch.py",
706706
"core/functional_tests/dynamic_configs/tests_kill_switches/test_no_initial_value.py":"taxi/uservices/userver/core/functional_tests/dynamic_configs/tests_kill_switches/test_no_initial_value.py",
707+
"core/functional_tests/early_monitor_port_open/CMakeLists.txt":"taxi/uservices/userver/core/functional_tests/early_monitor_port_open/CMakeLists.txt",
708+
"core/functional_tests/early_monitor_port_open/main.cpp":"taxi/uservices/userver/core/functional_tests/early_monitor_port_open/main.cpp",
709+
"core/functional_tests/early_monitor_port_open/static_config.yaml":"taxi/uservices/userver/core/functional_tests/early_monitor_port_open/static_config.yaml",
710+
"core/functional_tests/early_monitor_port_open/tests/conftest.py":"taxi/uservices/userver/core/functional_tests/early_monitor_port_open/tests/conftest.py",
711+
"core/functional_tests/early_monitor_port_open/tests/test_boot.py":"taxi/uservices/userver/core/functional_tests/early_monitor_port_open/tests/test_boot.py",
707712
"core/functional_tests/graceful_shutdown/CMakeLists.txt":"taxi/uservices/userver/core/functional_tests/graceful_shutdown/CMakeLists.txt",
708713
"core/functional_tests/graceful_shutdown/main.cpp":"taxi/uservices/userver/core/functional_tests/graceful_shutdown/main.cpp",
709714
"core/functional_tests/graceful_shutdown/src/handler_sigterm.hpp":"taxi/uservices/userver/core/functional_tests/graceful_shutdown/src/handler_sigterm.hpp",
@@ -1323,6 +1328,7 @@
13231328
"core/src/concurrent/background_task_storage_test.cpp":"taxi/uservices/userver/core/src/concurrent/background_task_storage_test.cpp",
13241329
"core/src/concurrent/conflated_event_channel.cpp":"taxi/uservices/userver/core/src/concurrent/conflated_event_channel.cpp",
13251330
"core/src/concurrent/conflated_event_channel_test.cpp":"taxi/uservices/userver/core/src/concurrent/conflated_event_channel_test.cpp",
1331+
"core/src/concurrent/fast_variable.hpp":"taxi/uservices/userver/core/src/concurrent/fast_variable.hpp",
13261332
"core/src/concurrent/impl/asymmetric_fence.cpp":"taxi/uservices/userver/core/src/concurrent/impl/asymmetric_fence.cpp",
13271333
"core/src/concurrent/impl/fast_atomic.hpp":"taxi/uservices/userver/core/src/concurrent/impl/fast_atomic.hpp",
13281334
"core/src/concurrent/impl/interference_shield_test.cpp":"taxi/uservices/userver/core/src/concurrent/impl/interference_shield_test.cpp",

core/functional_tests/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-basic-chaos)
88
add_subdirectory(dump_coroutines)
99
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-dump-coroutines)
1010

11+
add_subdirectory(early_monitor_port_open)
12+
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-early-monitor-port-open)
13+
1114
add_subdirectory(dynamic_configs)
1215
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-dynamic-configs)
1316

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
project(userver-core-tests-early-monitor-port-open CXX)
2+
3+
file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*pp")
4+
add_executable(${PROJECT_NAME} ${SOURCES} "main.cpp")
5+
target_link_libraries(${PROJECT_NAME} userver::core)
6+
7+
userver_chaos_testsuite_add()
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include <userver/components/component_context.hpp>
2+
#include <userver/components/minimal_server_component_list.hpp>
3+
#include <userver/engine/sleep.hpp>
4+
#include <userver/server/handlers/ping.hpp>
5+
#include <userver/utest/using_namespace_userver.hpp>
6+
#include <userver/utils/daemon_run.hpp>
7+
8+
class MonitorHandler final : public server::handlers::HttpHandlerBase {
9+
public:
10+
MonitorHandler(const components::ComponentConfig& config, const components::ComponentContext& context)
11+
: server::handlers::HttpHandlerBase(config, context, true) {}
12+
13+
static constexpr std::string_view kName = "handler-monitor";
14+
15+
std::string HandleRequestThrow(const server::http::HttpRequest&, server::request::RequestContext&) const override {
16+
called_ = true;
17+
return {};
18+
}
19+
20+
bool WasCalled() const { return called_; }
21+
22+
private:
23+
mutable std::atomic<bool> called_{false};
24+
};
25+
26+
class Brake final : public components::ComponentBase {
27+
public:
28+
Brake(const components::ComponentConfig& config, const components::ComponentContext& context)
29+
: components::ComponentBase(config, context) {
30+
auto& monitor_handler = context.FindComponent<MonitorHandler>();
31+
32+
for (;;) {
33+
engine::SleepFor(std::chrono::milliseconds(100));
34+
35+
if (monitor_handler.WasCalled()) {
36+
break;
37+
}
38+
}
39+
}
40+
41+
static constexpr std::string_view kName = "brake";
42+
43+
private:
44+
};
45+
46+
template <>
47+
inline constexpr bool components::kHasValidate<Brake> = false;
48+
49+
template <>
50+
inline constexpr auto components::kConfigFileMode<Brake> = ConfigFileMode::kNotRequired;
51+
52+
int main(int argc, char* argv[]) {
53+
const auto component_list =
54+
components::MinimalServerComponentList()
55+
.Append<server::handlers::Ping>()
56+
.Append<Brake>()
57+
.Append<MonitorHandler>();
58+
return utils::DaemonMain(argc, argv, component_list);
59+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# yaml
2+
# [graceful_shutdown_interval]
3+
components_manager:
4+
graceful_shutdown_interval: 10s
5+
# [graceful_shutdown_interval]
6+
7+
task_processors:
8+
main-task-processor:
9+
worker_threads: 4
10+
11+
fs-task-processor:
12+
worker_threads: 2
13+
14+
default_task_processor: main-task-processor
15+
16+
components:
17+
logging:
18+
fs-task-processor: fs-task-processor
19+
loggers:
20+
default:
21+
file_path: '@stderr'
22+
level: debug
23+
overflow_behavior: discard
24+
25+
server:
26+
listener:
27+
port: 8080
28+
task_processor: main-task-processor
29+
listener-monitor:
30+
port: 8081
31+
task_processor: main-task-processor
32+
33+
handler-ping:
34+
path: /ping
35+
method: GET
36+
task_processor: main-task-processor
37+
throttling_enabled: false
38+
handler-monitor:
39+
path: /monitor
40+
method: GET
41+
task_processor: main-task-processor
42+
throttling_enabled: false
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import pytest
2+
3+
pytest_plugins = ['pytest_userver.plugins.core']
4+
5+
6+
# Overriding a userver fixture
7+
@pytest.fixture(name='userver_config_testsuite', scope='session')
8+
def _userver_config_testsuite(userver_config_testsuite):
9+
def patch_config(config, config_vars) -> None:
10+
userver_config_testsuite(config, config_vars)
11+
# Restore the option after it's deleted by the base fixture.
12+
# Don't do this in your testsuite tests! For userver tests only.
13+
config['components_manager']['graceful_shutdown_interval'] = '3s'
14+
15+
return patch_config
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import asyncio
2+
3+
import aiohttp
4+
import pytest
5+
6+
7+
@pytest.mark.skip(reason='the feature is not yet enabled')
8+
async def test_monitor_port_is_open_before_all_components_are_ready(
9+
ensure_daemon_started,
10+
service_daemon_scope,
11+
service_baseurl,
12+
monitor_baseurl,
13+
):
14+
daemon_task = asyncio.create_task(ensure_daemon_started(service_daemon_scope))
15+
16+
# call /monitor
17+
async with aiohttp.ClientSession() as session:
18+
for i in range(120):
19+
try:
20+
response = await session.get(monitor_baseurl + 'monitor')
21+
if response.status == 200:
22+
break
23+
await asyncio.sleep(0.5)
24+
except aiohttp.ClientConnectorError:
25+
await asyncio.sleep(0.5)
26+
else:
27+
assert False, 'Service has not started'
28+
29+
# make sure /ping is now ready
30+
await daemon_task
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#pragma once
2+
3+
#include <userver/concurrent/variable.hpp>
4+
#include <userver/utils/assert.hpp>
5+
6+
USERVER_NAMESPACE_BEGIN
7+
8+
namespace concurrent {
9+
10+
template <typename Data, typename Mutex = engine::Mutex>
11+
class FastVariable final {
12+
public:
13+
template <typename... Arg>
14+
FastVariable(Arg&&... arg)
15+
: var_(std::forward<Arg>(arg)...)
16+
{}
17+
18+
void DisableWrites() { writes_disabled_ = true; }
19+
20+
bool AreWritesDisabled() const { return writes_disabled_; }
21+
22+
LockedPtr<std::unique_lock<Mutex>, Data> UniqueLock() {
23+
UINVARIANT(!writes_disabled_, "Writes are disabled");
24+
return var_.UniqueLock();
25+
}
26+
27+
// Slow bore DisableWrites(), very fast afterwards.
28+
LockedPtr<std::unique_lock<Mutex>, const Data> SharedLock() const {
29+
if (writes_disabled_) {
30+
return {{}, var_.GetDataUnsafe()};
31+
} else {
32+
return var_.UniqueLock();
33+
}
34+
}
35+
36+
private:
37+
std::atomic<bool> writes_disabled_{false};
38+
Variable<Data, Mutex> var_;
39+
};
40+
41+
} // namespace concurrent
42+
43+
USERVER_NAMESPACE_END

core/src/server/http/fixed_path_index.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,18 @@ void FixedPathIndex::AddHandler(
3030
const handlers::HttpHandlerBase& handler,
3131
engine::TaskProcessor& task_processor
3232
) {
33-
handler_method_index_map_[std::move(path)].AddHandler(handler, task_processor, {});
33+
auto handler_method_index_map = handler_method_index_map_.UniqueLock();
34+
(*handler_method_index_map)[std::move(path)].AddHandler(handler, task_processor, {});
3435
}
3536

37+
void FixedPathIndex::SetRegistrationFinished() { handler_method_index_map_.DisableWrites(); }
38+
39+
bool FixedPathIndex::IsRegistrationFinished() const { return handler_method_index_map_.AreWritesDisabled(); }
40+
3641
bool FixedPathIndex::MatchRequest(HttpMethod method, const std::string& path, MatchRequestResult& match_result) const {
37-
auto it = handler_method_index_map_.find(path);
38-
if (it == handler_method_index_map_.end()) {
42+
auto handler_method_index_map = handler_method_index_map_.SharedLock();
43+
auto it = handler_method_index_map->find(path);
44+
if (it == handler_method_index_map->end()) {
3945
return false;
4046
}
4147

core/src/server/http/fixed_path_index.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55

66
#include <userver/engine/task/task_processor_fwd.hpp>
77

8+
#include <concurrent/fast_variable.hpp>
89
#include <server/http/handler_info_index.hpp>
910
#include <server/http/handler_method_index.hpp>
11+
#include <userver/engine/mutex.hpp>
1012
#include <userver/server/handlers/http_handler_base.hpp>
1113
#include <userver/server/http/http_method.hpp>
1214

@@ -17,12 +19,15 @@ namespace server::http::impl {
1719
class FixedPathIndex final {
1820
public:
1921
void AddHandler(const handlers::HttpHandlerBase& handler, engine::TaskProcessor& task_processor);
22+
void SetRegistrationFinished();
23+
bool IsRegistrationFinished() const;
24+
2025
bool MatchRequest(HttpMethod method, const std::string& path, MatchRequestResult& match_result) const;
2126

2227
private:
2328
void AddHandler(std::string path, const handlers::HttpHandlerBase& handler, engine::TaskProcessor& task_processor);
2429

25-
std::unordered_map<std::string, HandlerMethodIndex> handler_method_index_map_;
30+
concurrent::FastVariable<std::unordered_map<std::string, HandlerMethodIndex>> handler_method_index_map_;
2631
};
2732

2833
} // namespace server::http::impl

0 commit comments

Comments
 (0)