Skip to content

Commit 04554bf

Browse files
committed
feat docs: more information on how to migrate to service template from an easy library
Tests: на прод не влияет, протестировано CI commit_hash:041852bade48cd095980bad5e869dfc52f815d59
1 parent f8fab8c commit 04554bf

File tree

19 files changed

+540
-15
lines changed

19 files changed

+540
-15
lines changed

.mapping.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,6 +2203,18 @@
22032203
"libraries/easy/samples/4_custom_dependency/main.cpp":"taxi/uservices/userver/libraries/easy/samples/4_custom_dependency/main.cpp",
22042204
"libraries/easy/samples/4_custom_dependency/testsuite/conftest.py":"taxi/uservices/userver/libraries/easy/samples/4_custom_dependency/testsuite/conftest.py",
22052205
"libraries/easy/samples/4_custom_dependency/testsuite/test_basic.py":"taxi/uservices/userver/libraries/easy/samples/4_custom_dependency/testsuite/test_basic.py",
2206+
"libraries/easy/samples/5_pg_service_template/CMakeLists.txt":"taxi/uservices/userver/libraries/easy/samples/5_pg_service_template/CMakeLists.txt",
2207+
"libraries/easy/samples/5_pg_service_template/configs/static_config.yaml":"taxi/uservices/userver/libraries/easy/samples/5_pg_service_template/configs/static_config.yaml",
2208+
"libraries/easy/samples/5_pg_service_template/postgresql/schemas/db_1.sql":"taxi/uservices/userver/libraries/easy/samples/5_pg_service_template/postgresql/schemas/db_1.sql",
2209+
"libraries/easy/samples/5_pg_service_template/src/main.cpp":"taxi/uservices/userver/libraries/easy/samples/5_pg_service_template/src/main.cpp",
2210+
"libraries/easy/samples/5_pg_service_template/testsuite/conftest.py":"taxi/uservices/userver/libraries/easy/samples/5_pg_service_template/testsuite/conftest.py",
2211+
"libraries/easy/samples/5_pg_service_template/testsuite/test_basic.py":"taxi/uservices/userver/libraries/easy/samples/5_pg_service_template/testsuite/test_basic.py",
2212+
"libraries/easy/samples/6_pg_service_template_no_http_with/CMakeLists.txt":"taxi/uservices/userver/libraries/easy/samples/6_pg_service_template_no_http_with/CMakeLists.txt",
2213+
"libraries/easy/samples/6_pg_service_template_no_http_with/configs/static_config.yaml":"taxi/uservices/userver/libraries/easy/samples/6_pg_service_template_no_http_with/configs/static_config.yaml",
2214+
"libraries/easy/samples/6_pg_service_template_no_http_with/postgresql/schemas/db_1.sql":"taxi/uservices/userver/libraries/easy/samples/6_pg_service_template_no_http_with/postgresql/schemas/db_1.sql",
2215+
"libraries/easy/samples/6_pg_service_template_no_http_with/src/main.cpp":"taxi/uservices/userver/libraries/easy/samples/6_pg_service_template_no_http_with/src/main.cpp",
2216+
"libraries/easy/samples/6_pg_service_template_no_http_with/testsuite/conftest.py":"taxi/uservices/userver/libraries/easy/samples/6_pg_service_template_no_http_with/testsuite/conftest.py",
2217+
"libraries/easy/samples/6_pg_service_template_no_http_with/testsuite/test_basic.py":"taxi/uservices/userver/libraries/easy/samples/6_pg_service_template_no_http_with/testsuite/test_basic.py",
22062218
"libraries/easy/samples/CMakeLists.txt":"taxi/uservices/userver/libraries/easy/samples/CMakeLists.txt",
22072219
"libraries/easy/src/easy.cpp":"taxi/uservices/userver/libraries/easy/src/easy.cpp",
22082220
"libraries/grpc-reflection/CMakeLists.txt":"taxi/uservices/userver/libraries/grpc-reflection/CMakeLists.txt",

libraries/easy/include/userver/easy.hpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,22 @@ class DependenciesBase : public components::ComponentBase {
3131
virtual ~DependenciesBase();
3232
};
3333

34+
} // namespace impl
35+
36+
/// @ingroup userver_components
37+
///
38+
/// @brief Factory component for the dependencies from easy library.
39+
///
40+
/// This component can be registered in the component list and used by any client. For example:
41+
///
42+
/// @snippet libraries/easy/samples/6_pg_service_template_no_http_with/src/main.cpp main
3443
template <class Dependencies>
35-
class DependenciesComponent : public DependenciesBase {
44+
class DependenciesComponent : public impl::DependenciesBase {
3645
public:
46+
/// @ingroup userver_component_names
47+
/// @brief The default name of easy::DependenciesComponent
48+
static constexpr std::string_view kName = "easy-dependencies";
49+
3750
DependenciesComponent(const components::ComponentConfig& config, const components::ComponentContext& context)
3851
: DependenciesBase(config, context), dependencies_(context) {}
3952

@@ -43,8 +56,6 @@ class DependenciesComponent : public DependenciesBase {
4356
Dependencies dependencies_;
4457
};
4558

46-
} // namespace impl
47-
4859
/// @brief easy::HttpWith like class with erased dependencies information that should be used only in dependency
4960
/// registration functions; use easy::HttpWith if not making a new dependency class.
5061
class HttpBase final {
@@ -229,7 +240,7 @@ class HttpWith final {
229240
}
230241

231242
private:
232-
using DependenciesComponent = impl::DependenciesComponent<Dependency>;
243+
using DependenciesComponent = easy::DependenciesComponent<Dependency>;
233244
HttpBase impl_;
234245
};
235246

@@ -312,7 +323,7 @@ class HttpDep {
312323
} // namespace easy
313324

314325
template <class Dependencies>
315-
inline constexpr auto components::kConfigFileMode<easy::impl::DependenciesComponent<Dependencies>> =
326+
inline constexpr auto components::kConfigFileMode<easy::DependenciesComponent<Dependencies>> =
316327
ConfigFileMode::kNotRequired;
317328

318329
USERVER_NAMESPACE_END
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
project(userver-easy-samples-pg-service-template CXX)
2+
3+
add_executable(${PROJECT_NAME} "src/main.cpp")
4+
target_link_libraries(${PROJECT_NAME} userver::easy)
5+
6+
userver_testsuite_add_simple()
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# yaml
2+
components_manager:
3+
task_processors: # Task processor is an executor for coroutine tasks
4+
main-task-processor: # Make a task processor for CPU-bound coroutine tasks.
5+
worker_threads: 4 # Process tasks in 4 threads.
6+
7+
fs-task-processor: # Make a separate task processor for filesystem bound tasks.
8+
worker_threads: 1
9+
10+
default_task_processor: main-task-processor # Task processor in which components start.
11+
12+
components: # Configuring components that were registered via component_list
13+
/log-POST:
14+
path: /log # Registering handler by URL '/log'.
15+
method: POST
16+
task_processor: main-task-processor # Run it on CPU bound task processor
17+
18+
action-client:
19+
service-url: http://some-service.example/v1/action
20+
21+
http-client:
22+
pool-statistics-disable: false
23+
thread-name-prefix: http-client
24+
threads: 2
25+
fs-task-processor: fs-task-processor
26+
27+
postgres:
28+
dbconnection#env: POSTGRESQL
29+
dbconnection#fallback: 'postgresql://testsuite@localhost:15433/postgres'
30+
blocking_task_processor: fs-task-processor
31+
dns_resolver: async
32+
33+
testsuite-support: {}
34+
35+
dns-client:
36+
fs-task-processor: fs-task-processor
37+
38+
server:
39+
listener: # configuring the main listening socket...
40+
port: 8080 # ...to listen on this port and...
41+
task_processor: main-task-processor # ...process incoming requests on this task processor.
42+
43+
logging:
44+
fs-task-processor: fs-task-processor
45+
loggers:
46+
default:
47+
file_path: '@stderr'
48+
level: debug
49+
overflow_behavior: discard # Drop logs if the system is too busy to write them down.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
CREATE TABLE IF NOT EXISTS events_table (
3+
id serial NOT NULL,
4+
action VARCHAR PRIMARY KEY
5+
)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include <userver/utest/using_namespace_userver.hpp> // Note: this is for the purposes of samples only
2+
3+
#include <userver/easy.hpp>
4+
#include <userver/yaml_config/merge_schemas.hpp>
5+
6+
#include <userver/clients/http/component.hpp>
7+
#include <userver/components/component_context.hpp>
8+
9+
/// [ActionClient]
10+
class ActionClient : public components::ComponentBase {
11+
public:
12+
static constexpr std::string_view kName = "action-client";
13+
14+
ActionClient(const components::ComponentConfig& config, const components::ComponentContext& context)
15+
: ComponentBase{config, context},
16+
service_url_(config["service-url"].As<std::string>()),
17+
http_client_(context.FindComponent<components::HttpClient>().GetHttpClient()) {}
18+
19+
auto CreateHttpRequest(std::string action) const {
20+
return http_client_.CreateRequest().url(service_url_).post().data(std::move(action)).perform();
21+
}
22+
23+
static yaml_config::Schema GetStaticConfigSchema() {
24+
return yaml_config::MergeSchemas<components::ComponentBase>(R"(
25+
type: object
26+
description: My dependencies schema
27+
additionalProperties: false
28+
properties:
29+
service-url:
30+
type: string
31+
description: URL of the service to send the actions to
32+
)");
33+
}
34+
35+
private:
36+
const std::string service_url_;
37+
clients::http::Client& http_client_;
38+
};
39+
/// [ActionClient]
40+
41+
/// [ActionDep]
42+
class ActionDep {
43+
public:
44+
explicit ActionDep(const components::ComponentContext& config) : component_{config.FindComponent<ActionClient>()} {}
45+
auto CreateActionRequest(std::string action) const { return component_.CreateHttpRequest(std::move(action)); }
46+
47+
static void RegisterOn(easy::HttpBase& app) {
48+
app.TryAddComponent<ActionClient>(ActionClient::kName, "service-url: http://some-service.example/v1/action");
49+
easy::HttpDep::RegisterOn(app);
50+
}
51+
52+
private:
53+
ActionClient& component_;
54+
};
55+
/// [ActionDep]
56+
57+
/// [main]
58+
int main(int argc, char* argv[]) {
59+
using Deps = easy::Dependencies<ActionDep, easy::PgDep>;
60+
61+
easy::HttpWith<Deps>(argc, argv)
62+
.DefaultContentType(http::content_type::kTextPlain)
63+
.Post("/log", [](const server::http::HttpRequest& req, const Deps& deps) {
64+
const auto& action = req.GetArg("action");
65+
deps.pg().Execute(
66+
storages::postgres::ClusterHostType::kMaster, "INSERT INTO events_table(action) VALUES($1)", action
67+
);
68+
return deps.CreateActionRequest(action)->body();
69+
});
70+
}
71+
/// [main]
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import pathlib
2+
3+
import pytest
4+
5+
from testsuite.databases.pgsql import discover
6+
7+
pytest_plugins = ['pytest_userver.plugins.postgresql']
8+
9+
USERVER_CONFIG_HOOKS = ['userver_actions_service']
10+
11+
12+
@pytest.fixture(scope='session')
13+
def service_source_dir():
14+
"""Path to root directory service."""
15+
return pathlib.Path(__file__).parent.parent
16+
17+
18+
@pytest.fixture(scope='session')
19+
def initial_data_path(service_source_dir):
20+
"""Path for find files with data"""
21+
return [service_source_dir / 'postgresql/data']
22+
23+
24+
@pytest.fixture(scope='session')
25+
def userver_actions_service(mockserver_info):
26+
def do_patch(config_yaml, config_vars):
27+
components = config_yaml['components_manager']['components']
28+
components['action-client']['service-url'] = mockserver_info.url(
29+
'/v1/action',
30+
)
31+
32+
return do_patch
33+
34+
35+
@pytest.fixture(scope='session')
36+
def pgsql_local(service_source_dir, pgsql_local_create):
37+
"""Create schemas databases for tests"""
38+
databases = discover.find_schemas(
39+
'pg_service_template', # service name that goes to the DB connection
40+
[service_source_dir.joinpath('postgresql/schemas')],
41+
)
42+
return pgsql_local_create(list(databases.values()))
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
async def test_log_action(service_client, pgsql, mockserver):
2+
@mockserver.handler('/v1/action')
3+
def _mock(request):
4+
assert (
5+
request.get_data() == b'test_1'
6+
), f'Actual data is {request.get_data()}'
7+
return mockserver.make_response()
8+
9+
response = await service_client.post('/log?action=test_1')
10+
assert response.status == 200
11+
12+
# There is a 'postgresql/schemas/db_1.sql' file, so the database is 'db_1'
13+
cursor = pgsql['db_1'].cursor()
14+
cursor.execute('SELECT action FROM events_table WHERE id=1')
15+
result = cursor.fetchall()
16+
assert len(result) == 1
17+
assert result[0][0] == 'test_1'
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
project(userver-easy-samples-pg-service-template-no-http-with CXX)
2+
3+
add_executable(${PROJECT_NAME} "src/main.cpp")
4+
target_link_libraries(${PROJECT_NAME} userver::easy)
5+
6+
userver_testsuite_add_simple()
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# yaml
2+
components_manager:
3+
task_processors: # Task processor is an executor for coroutine tasks
4+
main-task-processor: # Make a task processor for CPU-bound coroutine tasks.
5+
worker_threads: 4 # Process tasks in 4 threads.
6+
7+
fs-task-processor: # Make a separate task processor for filesystem bound tasks.
8+
worker_threads: 1
9+
10+
default_task_processor: main-task-processor # Task processor in which components start.
11+
12+
components: # Configuring components that were registered via component_list
13+
/log-POST:
14+
path: /log # Registering handler by URL '/log'.
15+
method: POST
16+
task_processor: main-task-processor # Run it on CPU bound task processor
17+
18+
action-client:
19+
service-url: http://some-service.example/v1/action
20+
21+
http-client:
22+
pool-statistics-disable: false
23+
thread-name-prefix: http-client
24+
threads: 2
25+
fs-task-processor: fs-task-processor
26+
27+
postgres:
28+
dbconnection#env: POSTGRESQL
29+
dbconnection#fallback: 'postgresql://testsuite@localhost:15433/postgres'
30+
blocking_task_processor: fs-task-processor
31+
dns_resolver: async
32+
33+
testsuite-support: {}
34+
35+
dns-client:
36+
fs-task-processor: fs-task-processor
37+
38+
server:
39+
listener: # configuring the main listening socket...
40+
port: 8080 # ...to listen on this port and...
41+
task_processor: main-task-processor # ...process incoming requests on this task processor.
42+
43+
logging:
44+
fs-task-processor: fs-task-processor
45+
loggers:
46+
default:
47+
file_path: '@stderr'
48+
level: debug
49+
overflow_behavior: discard # Drop logs if the system is too busy to write them down.

0 commit comments

Comments
 (0)