Skip to content

Commit 0feffed

Browse files
committed
feat docs: use schemas in core for docs in more cases
Also improve diagnostics for utils::FindResource Tests: протестировано в CI, проверено локально что все поля отображаются и форматируются приятно для глаза (или хотя бы как было раньше) commit_hash:1880366a72b980ec3fb3e76658c7454414ca38c5
1 parent 4f37c91 commit 0feffed

File tree

10 files changed

+77
-95
lines changed

10 files changed

+77
-95
lines changed

core/include/userver/cache/caching_component_base.hpp

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ USERVER_NAMESPACE_BEGIN
3131

3232
namespace components {
3333

34-
// clang-format off
35-
3634
/// @ingroup userver_components userver_base_classes
3735
///
3836
/// @brief Base class for caching components
@@ -53,30 +51,11 @@ namespace components {
5351
/// * @ref USERVER_CACHES
5452
/// * @ref USERVER_DUMPS
5553
///
56-
/// ## Static options:
54+
/// ## Static options of @ref components::CachingComponentBase :
55+
/// @include{doc} scripts/docs/en/components_schema/core/src/cache/caching_component_base.md
5756
///
58-
/// Name | Description | Default value
59-
/// ---- | ----------- | -------------
60-
/// update-types | specifies whether incremental and/or full updates will be used | see below
61-
/// update-interval | (*required*) interval between Update invocations | --
62-
/// update-jitter | max. amount of time by which update-interval may be adjusted for requests dispersal | update_interval / 10
63-
/// full-update-interval | interval between full updates | --
64-
/// full-update-jitter | max. amount of time by which full-update-interval may be adjusted for requests dispersal | full-update-interval / 10
65-
/// updates-enabled | if false, cache updates are disabled (except for the first one if !first-update-fail-ok) | true
66-
/// first-update-fail-ok | whether first update failure is non-fatal; see also @ref MayReturnNull | false
67-
/// task-processor | the name of the TaskProcessor for running DoWork | main-task-processor
68-
/// config-settings | enables dynamic reconfiguration with CacheConfigSet | true
69-
/// exception-interval | Used instead of `update-interval` in case of exception | update_interval
70-
/// additional-cleanup-interval | how often to run background RCU garbage collector | 10 seconds
71-
/// is-strong-period | whether to include Update execution time in update-interval | false
72-
/// testsuite-force-periodic-update | override testsuite-periodic-update-enabled in TestsuiteSupport component config | --
73-
/// failed-updates-before-expiration | the number of consecutive failed updates for data expiration | --
74-
/// has-pre-assign-check | enables the check before changing the value in the cache, by default it is the check that the new value is not empty | false
75-
/// alert-on-failing-to-update-times | fire an alert if the cache update failed specified amount of times in a row. If zero - alerts are disabled. Value from dynamic config takes priority over static | 0
76-
/// safe-data-lifetime | enables awaiting data destructors in the component's destructor. Can be set to `false` if the stored data does not refer to the component and its dependencies. | true
77-
/// dump.* | Manages cache behavior after dump load | -
78-
/// dump.first-update-mode | Behavior of update after successful load from dump. See info on modes below | skip
79-
/// dump.first-update-type | Update type after successful load from dump (`full`, `incremental` or `incremental-then-async-full`) | full
57+
/// Options inherited from @ref components::ComponentBase :
58+
/// @include{doc} scripts/docs/en/components_schema/core/src/components/impl/component_base.md
8059
///
8160
/// ### Update types
8261
/// * `full-and-incremental`: both `update-interval` and `full-update-interval`
@@ -103,7 +82,8 @@ namespace components {
10382
/// * size of database: 1000 objects
10483
/// * removal rate: 30 objects per minute (0.5 objects per second)
10584
///
106-
/// Let's say we allow 20% extra garbage objects in cache in addition to the actual objects from the database. In this case we need:
85+
/// Let's say we allow 20% extra garbage objects in cache in addition to the actual objects from the database. In this
86+
/// case we need:
10787
///
10888
/// full-update-interval = (size-of-database * 20% / removal-rate) = 400s
10989
///
@@ -132,11 +112,11 @@ namespace components {
132112
///
133113
/// Further customizes the behavior of @ref dump::Dumper "cache dumps".
134114
///
135-
/// Mode | Description
136-
/// ------------- | -----------
137-
/// `skip` | after successful load from dump, do nothing
138-
/// `required` | make a synchronous update of type `first-update-type`, stop the service on failure
139-
/// `best-effort` | make a synchronous update of type `first-update-type`, keep working and use data from dump on failure
115+
/// Mode | Description
116+
/// ----------- | -----------
117+
/// skip | after successful load from dump, do nothing
118+
/// required | make a synchronous update of type `first-update-type`, stop the service on failure
119+
/// best-effort | make a synchronous update of type `first-update-type`, keep working and use data from dump on failure
140120
///
141121
/// ### testsuite-force-periodic-update
142122
/// use it to enable periodic cache update for a component in testsuite environment
@@ -151,9 +131,6 @@ namespace components {
151131
///
152132
/// @see @ref scripts/docs/en/userver/caches.md. pytest_userver.client.Client.invalidate_caches()
153133
/// for a function to force cache update from testsuite.
154-
155-
// clang-format on
156-
157134
template <typename T>
158135
// NOLINTNEXTLINE(fuchsia-multiple-inheritance)
159136
class CachingComponentBase : public ComponentBase, public cache::DataProvider<T>, protected cache::CacheUpdateTrait {

core/include/userver/cache/lru_cache_component_base.hpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ yaml_config::Schema GetLruCacheComponentBaseSchema();
3838

3939
} // namespace impl
4040

41-
// clang-format off
42-
4341
/// @ingroup userver_components userver_base_classes
4442
///
4543
/// @brief Base class for LRU-cache components
@@ -53,14 +51,11 @@ yaml_config::Schema GetLruCacheComponentBaseSchema();
5351
/// ## LruCacheComponent Dynamic config
5452
/// * @ref USERVER_LRU_CACHES
5553
///
56-
/// ## Static options:
57-
/// Name | Description | Default value
58-
/// ---- | ----------- | -------------
59-
/// size | max amount of items to store in cache | --
60-
/// ways | number of ways for associative cache | --
61-
/// lifetime | TTL for cache entries (0 is unlimited) | 0
62-
/// background-update | enables asynchronous updates for expiring values | false
63-
/// config-settings | enables dynamic reconfiguration with CacheConfigSet | true
54+
/// ## Static options of @ref cache::LruCacheComponent :
55+
/// @include{doc} scripts/docs/en/components_schema/core/src/cache/lru_cache_component_base.md
56+
///
57+
/// Options inherited from @ref components::ComponentBase :
58+
/// @include{doc} scripts/docs/en/components_schema/core/src/components/impl/component_base.md
6459
///
6560
/// ## Example usage:
6661
///
@@ -71,8 +66,6 @@ yaml_config::Schema GetLruCacheComponentBaseSchema();
7166
///
7267
/// ## Example config:
7368
/// @snippet cache/lru_cache_component_base_test.cpp Sample lru cache component config
74-
75-
// clang-format on
7669
template <typename Key, typename Value, typename Hash = std::hash<Key>, typename Equal = std::equal_to<Key>>
7770
// NOLINTNEXTLINE(fuchsia-multiple-inheritance)
7871
class LruCacheComponent : public components::ComponentBase, private dump::DumpableEntity {

core/include/userver/clients/http/component.hpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ USERVER_NAMESPACE_BEGIN
1515

1616
namespace components {
1717

18-
// clang-format off
19-
2018
/// @ingroup userver_components
2119
///
2220
/// @brief Component that manages @ref clients::http::ClientWithPlugins.
@@ -27,17 +25,15 @@ namespace components {
2725
/// Returned references to @ref clients::http::Client live for a lifetime of the
2826
/// component and are safe for concurrent use.
2927
///
30-
/// ## Static options:
31-
/// Name | Description | Default value
32-
/// ---- | ----------- | -------------
33-
/// core-component | name of components::HttpClientCore component to use | 'http-client-core'
34-
/// plugins | map of plugins to apply, plugin-name -> ordering index. A plugin component is called "http-client-plugin-" plus the plugin name. | {}
28+
/// ## Static options of @ref components::HttpClient :
29+
/// @include{doc} scripts/docs/en/components_schema/core/src/clients/http/component.md
30+
///
31+
/// Options inherited from @ref components::ComponentBase :
32+
/// @include{doc} scripts/docs/en/components_schema/core/src/components/impl/component_base.md
3533
///
3634
/// ## Static configuration example:
3735
///
3836
/// @snippet components/common_component_list_test.cpp Sample http client component config
39-
40-
// clang-format on
4137
class HttpClient final : public ComponentBase {
4238
public:
4339
/// @ingroup userver_component_names

core/include/userver/clients/http/component_core.hpp

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,11 @@ namespace components {
3535
/// * @ref HTTP_CLIENT_CONNECT_THROTTLE
3636
/// * @ref HTTP_CLIENT_CONNECTION_POOL_SIZE
3737
///
38-
/// ## Static options:
39-
/// Name | Description | Default value
40-
/// ---- | ----------- | -------------
41-
/// pool-statistics-disable | set to true to disable statistics for connection pool | false
42-
/// thread-name-prefix | set OS thread name to this value | ''
43-
/// threads | number of threads to process low level HTTP related IO system calls | 8
44-
/// fs-task-processor | task processor to run blocking HTTP related calls, like DNS resolving or hosts reading | engine::current_task::GetBlockingTaskProcessor()
45-
/// destination-metrics-auto-max-size | set max number of automatically created destination metrics | 100
46-
/// user-agent | User-Agent HTTP header to show on all requests, result of utils::GetUserverIdentifier() if empty | empty
47-
/// testsuite-enabled | enable testsuite testing support | false
48-
/// testsuite-timeout | if set, force the request timeout regardless of the value passed in code | -
49-
/// testsuite-allowed-url-prefixes | if set, checks that all URLs start with any of the passed prefixes, asserts if not. Set for testing purposes only. | ''
50-
/// dns_resolver | server hostname resolver type (getaddrinfo or async) | 'async'
51-
/// set-deadline-propagation-header | whether to set http::common::kXYaTaxiClientTimeoutMs request header, see @ref scripts/docs/en/userver/deadline_propagation.md | true
52-
/// cancellation-policy | Cancellation policy for new requests. | cancel
38+
/// ## Static options @ref components::HttpClientCore :
39+
/// @include{doc} scripts/docs/en/components_schema/core/src/clients/http/component_core.md
40+
///
41+
/// Options inherited from @ref components::ComponentBase :
42+
/// @include{doc} scripts/docs/en/components_schema/core/src/components/impl/component_base.md
5343
///
5444
/// ## Static configuration example:
5545
///

core/src/cache/caching_component_base.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ properties:
3333
exception-interval:
3434
type: string
3535
description: sleep interval after an unhandled exception
36+
defaultDescription: update_interval
3637
first-update-fail-ok:
3738
type: boolean
3839
description: whether first update failure is non-fatal
@@ -103,6 +104,7 @@ properties:
103104
- skip
104105
- required
105106
- best-effort
107+
defaultDescription: skip
106108
first-update-type:
107109
type: string
108110
description: |

core/src/clients/http/component.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ additionalProperties: false
44
properties:
55
core-component:
66
type: string
7-
description: name of HttpClientCore component to use
7+
description: name of components::HttpClientCore component to use
88
defaultDescription: http-client-core
99
plugins:
1010
type: object
11-
description: HTTP client plugins
11+
description: map of plugins to apply, plugin-name -> ordering index. A plugin
12+
component is called "http-client-plugin-" plus the plugin name.
1213
properties: {}
1314
additionalProperties:
1415
type: integer

core/src/clients/http/component_core.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ properties:
2828
type: string
2929
description: User-Agent HTTP header to show on all requests, result of utils::GetUserverIdentifier()
3030
if empty
31-
defaultDescription: empty
31+
defaultDescription: ''
3232
testsuite-enabled:
3333
type: boolean
3434
description: enable testsuite testing support
@@ -46,7 +46,7 @@ properties:
4646
description: URL prefix
4747
dns_resolver:
4848
type: string
49-
description: server hostname resolver type (getaddrinfo or async)
49+
description: server hostname resolver type
5050
defaultDescription: 'async'
5151
enum:
5252
- getaddrinfo
@@ -65,3 +65,4 @@ properties:
6565
enum:
6666
- cancel
6767
- ignore
68+
defaultDescription: 'cancel'

scripts/docs/components_schema_to_table.py

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
import argparse
44
import os
55
import pathlib
6+
from typing import Any
67

78
import yaml
89

910
USERVER_ROOT = pathlib.Path(__file__).parent.parent.parent
1011

1112

12-
def normalize_default_value(data) -> str:
13+
def normalize_default_value(data: Any) -> str:
1314
if data is True:
1415
return 'true'
1516
elif data is False:
@@ -18,24 +19,35 @@ def normalize_default_value(data) -> str:
1819
return data
1920

2021

21-
def merge_descriptions(yaml, other):
22-
if yaml.get('description') and other.get('description'):
23-
description = yaml['description'].strip()
22+
def merge_descriptions(yaml_node: dict, other: dict) -> dict:
23+
if yaml_node.get('description') and other.get('description'):
24+
description = yaml_node['description'].strip()
25+
description = f'{description[0].upper()}{description[1:]}'
2426
if not description.endswith('.'):
2527
description += '.'
2628
description += ' <i>Each of the elements:</i> ' + other['description']
2729

28-
value_merged = yaml.copy()
30+
value_merged = yaml_node.copy()
2931
value_merged['description'] = description
3032
return value_merged
31-
elif yaml.get('description'):
32-
return yaml
33+
elif yaml_node.get('description'):
34+
return yaml_node
3335
else:
3436
return other
3537

3638

37-
def visit_object(yaml, prefix: str = ''):
38-
properties = yaml.get('properties', {})
39+
def enrich_description(yaml_node: dict) -> str:
40+
description = yaml_node['description'].replace('\n', ' ').strip()
41+
description = f'{description[0].upper()}{description[1:]}'
42+
if not description.endswith('.'):
43+
description += '.'
44+
if enum := yaml_node.get('enum'):
45+
description += ' <i>Possible values:</i> ' + ', '.join(str(x) for x in enum) + '.'
46+
return description
47+
48+
49+
def visit_object(yaml_node: dict, prefix: str = ''):
50+
properties = yaml_node.get('properties', {})
3951

4052
for key, value in properties.items():
4153
if value.get('type') == 'array':
@@ -49,37 +61,37 @@ def visit_object(yaml, prefix: str = ''):
4961
else:
5062
yield (prefix + key, value)
5163

52-
additionals = yaml.get('additionalProperties')
64+
additionals = yaml_node.get('additionalProperties')
5365
if additionals is True:
54-
yield (prefix + '*', yaml)
66+
yield (prefix + '*', yaml_node)
5567
elif not additionals:
5668
return
5769
elif additionals.get('type') == 'object':
58-
yield from visit_object(yaml['additionalProperties'], prefix + '*.')
70+
yield from visit_object(yaml_node['additionalProperties'], prefix + '*.')
5971
elif additionals.get('type') == 'array':
60-
value_merged = merge_descriptions(yaml, additionals['items'])
72+
value_merged = merge_descriptions(yaml_node, additionals['items'])
6173
yield (prefix + '*.[]', value_merged)
6274
else:
63-
value_merged = merge_descriptions(yaml, additionals)
75+
value_merged = merge_descriptions(yaml_node, additionals)
6476
yield (prefix + '*', value_merged)
6577

6678

67-
def format_schema(yaml) -> str:
79+
def format_schema(yaml_node: Any) -> str:
6880
result = ''
69-
key_values = list(visit_object(yaml))
81+
key_values = list(visit_object(yaml_node))
7082
if not key_values:
7183
result += 'No options'
7284
return result
7385

7486
max_key_size = max(len(key) for key, _ in key_values)
75-
max_value_size = max(len(value['description']) for _, value in key_values)
87+
max_value_size = max(len(enrich_description(value)) for _, value in key_values)
7688

7789
result += f'{"Name":{max_key_size}} | {"Description":{max_value_size}} | Default value\n'
7890
result += f'{"":-<{max_key_size}} | {"":-<{max_value_size}} | {"":-<16}\n'
7991

8092
for key, value in key_values:
8193
key = key.replace('\n', ' ')
82-
description = value['description'].replace('\n', ' ')
94+
description = enrich_description(value)
8395
default = normalize_default_value(value.get('defaultDescription', '--'))
8496
result += f'{key:{max_key_size}} | {description:{max_value_size}} | {default}\n'
8597

@@ -93,7 +105,7 @@ def parse_args():
93105
return parser.parse_args()
94106

95107

96-
def handle_file(ifname: pathlib.Path, output_dir: pathlib.Path):
108+
def handle_file(ifname: pathlib.Path, output_dir: pathlib.Path) -> None:
97109
with open(ifname) as ifile:
98110
content = yaml.load(ifile.read(), yaml.Loader)
99111

universal/include/userver/utils/resources.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ USERVER_NAMESPACE_BEGIN
99

1010
namespace utils {
1111

12+
/// Registeres a resource; used by `userver_embed_file` CMake function
1213
void RegisterResource(std::string_view name, std::string_view value);
1314

15+
/// Returns a resource by name, registered by `userver_embed_file` CMake function (or RESOURCE() macro in some
16+
/// other build systems)
1417
std::string FindResource(std::string_view name);
1518

1619
} // namespace utils

universal/src/utils/resources.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#include <userver/utils/resources.hpp>
22

3+
#include <fmt/format.h>
4+
5+
#include <stdexcept>
36
#include <unordered_map>
47

58
#if __has_include(<library/cpp/resource/resource.h>)
@@ -19,11 +22,15 @@ std::unordered_map<std::string_view, std::string_view>& Resources() {
1922
void RegisterResource(std::string_view name, std::string_view value) { Resources().emplace(name, value); }
2023

2124
std::string FindResource(std::string_view name) {
25+
try {
2226
#ifdef ARCADIA
23-
return NResource::Find(name);
27+
return NResource::Find(name);
2428
#else
25-
return std::string{Resources().at(name)};
29+
return std::string{Resources().at(name)};
2630
#endif
31+
} catch (const std::exception& e) {
32+
throw std::runtime_error(fmt::format("Failed to locate resource with name '{}': {}", name, e.what()));
33+
}
2734
}
2835

2936
} // namespace utils

0 commit comments

Comments
 (0)