Skip to content

Commit beaa933

Browse files
Enable direct conversion from configuration parameter to product_query (#186)
* Enable direct conversion from configuration parameter to product_query * Test parameter-retrieval failures --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent f691457 commit beaa933

19 files changed

+162
-37
lines changed

phlex/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ cet_make_library(
1717
Boost::boost
1818
Boost::json
1919
phlex::core
20+
phlex::configuration
2021
)
2122

2223
install(FILES concurrency.hpp module.hpp source.hpp DESTINATION include/phlex)
@@ -27,9 +28,11 @@ cet_make_library(
2728
EXPORT_NAME
2829
configuration
2930
INTERFACE
30-
NO_SOURCE
31+
SOURCE
32+
configuration.cpp
3133
LIBRARIES
3234
Boost::json
35+
phlex::core
3336
)
3437
install(FILES configuration.hpp DESTINATION include/phlex)
3538

phlex/configuration.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include "phlex/configuration.hpp"
2+
#include "phlex/core/product_query.hpp"
3+
4+
#include <ranges>
5+
#include <string>
6+
7+
namespace phlex::experimental {
8+
std::vector<std::string> configuration::keys() const
9+
{
10+
std::vector<std::string> result;
11+
result.reserve(config_.size());
12+
std::ranges::transform(
13+
config_, std::back_inserter(result), [](auto const& element) { return element.key(); });
14+
return result;
15+
}
16+
17+
configuration tag_invoke(boost::json::value_to_tag<configuration> const&,
18+
boost::json::value const& jv)
19+
{
20+
return configuration{jv.as_object()};
21+
}
22+
23+
product_query tag_invoke(boost::json::value_to_tag<product_query> const&,
24+
boost::json::value const& jv)
25+
{
26+
using detail::value_decorate_exception;
27+
auto query_object = jv.as_object();
28+
return product_query{.spec = {value_decorate_exception<std::string>(query_object, "product")},
29+
.layer = value_decorate_exception<std::string>(query_object, "layer")};
30+
}
31+
}

phlex/configuration.hpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,24 @@
22
#define PHLEX_CONFIGURATION_HPP
33

44
#include "boost/json.hpp"
5+
#include "phlex/core/product_query.hpp"
56

67
#include <optional>
8+
#include <string>
9+
#include <vector>
710

811
namespace phlex::experimental {
12+
13+
namespace detail {
14+
template <typename T>
15+
T value_decorate_exception(boost::json::object const& obj, std::string const& key)
16+
try {
17+
return value_to<T>(obj.at(key));
18+
} catch (std::exception const& e) {
19+
throw std::runtime_error("Error retrieving parameter '" + key + "':\n" + e.what());
20+
}
21+
}
22+
923
class configuration {
1024
public:
1125
configuration() = default;
@@ -14,16 +28,16 @@ namespace phlex::experimental {
1428
template <typename T>
1529
std::optional<T> get_if_present(std::string const& key) const
1630
{
17-
if (auto pkey = config_.if_contains(key)) {
18-
return value_to<T>(*pkey);
31+
if (config_.contains(key)) {
32+
return detail::value_decorate_exception<T>(config_, key);
1933
}
2034
return std::nullopt;
2135
}
2236

2337
template <typename T>
2438
T get(std::string const& key) const
2539
{
26-
return value_to<T>(config_.at(key));
40+
return detail::value_decorate_exception<T>(config_, key);
2741
}
2842

2943
template <typename T>
@@ -32,10 +46,21 @@ namespace phlex::experimental {
3246
return get_if_present<T>(key).value_or(std::forward<T>(default_value));
3347
}
3448

49+
std::vector<std::string> keys() const;
50+
3551
private:
3652
boost::json::object config_;
3753
};
3854

55+
// =================================================================================
56+
// To enable direct conversions from Boost JSON types to our own types, we implement
57+
// tag_invoke(...) function overloads, which are the customization points Boost JSON
58+
// provides.
59+
configuration tag_invoke(boost::json::value_to_tag<configuration> const&,
60+
boost::json::value const& jv);
61+
62+
product_query tag_invoke(boost::json::value_to_tag<product_query> const&,
63+
boost::json::value const& jv);
3964
}
4065

4166
#endif // PHLEX_CONFIGURATION_HPP

test/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ include(CetTest)
66
cet_test_env(SPDLOG_LEVEL=debug)
77

88
cet_test(concepts SOURCE concepts.cpp LIBRARIES phlex::core)
9+
cet_test(config_test USE_CATCH2_MAIN SOURCE configuration.cpp LIBRARIES
10+
phlex::configuration
11+
)
912
cet_test(string_literal SOURCE string_literal.cpp LIBRARIES phlex::utilities)
1013
cet_test(type_deduction SOURCE type_deduction.cpp LIBRARIES
1114
phlex::metaprogramming

test/benchmarks/accept_even_ids.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ PHLEX_EXPERIMENTAL_REGISTER_ALGORITHMS(m, config)
1010
"accept_even_ids",
1111
[](data_cell_index const& id) { return id.number() % 2 == 0; },
1212
concurrency::unlimited)
13-
.input_family(product_query{config.get<std::string>("product_name"), "event"});
13+
.input_family(config.get<product_query>("input"));
1414
}

test/benchmarks/accept_even_numbers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ PHLEX_EXPERIMENTAL_REGISTER_ALGORITHMS(m, config)
77
using namespace phlex::experimental;
88
m.predicate(
99
"accept_even_numbers", [](int i) { return i % 2 == 0; }, concurrency::unlimited)
10-
.input_family(product_query{config.get<std::string>("consumes"), "event"});
10+
.input_family(config.get<product_query>("consumes"));
1111
}

test/benchmarks/accept_fibonacci_numbers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ PHLEX_EXPERIMENTAL_REGISTER_ALGORITHMS(m, config)
88
using namespace phlex::experimental;
99
m.make<test::fibonacci_numbers>(config.get<int>("max_number"))
1010
.predicate("accept", &test::fibonacci_numbers::accept, concurrency::unlimited)
11-
.input_family(product_query{config.get<std::string>("consumes"), "event"});
11+
.input_family(config.get<product_query>("consumes"));
1212
}

test/benchmarks/benchmark-04.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
read_index: {
1111
plugin: 'read_index',
12-
consumes: 'a'
12+
consumes: { product: 'a', layer: "event" }
1313
},
1414
provider: {
1515
plugin: 'benchmarks_provider'

test/benchmarks/benchmark-07.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
modules: {
77
even_filter: {
88
plugin: 'accept_even_ids',
9-
product_name: 'id',
9+
input: { product: 'id', layer: 'event' },
1010
},
1111
b_creator: {
1212
plugin: 'last_index',

test/benchmarks/benchmark-08.jsonnet

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ local max_number = 100000;
1212
},
1313
even_filter: {
1414
plugin: 'accept_even_numbers',
15-
consumes: 'a',
15+
consumes: { product: 'a', layer: 'event' }
1616
},
1717
fibonacci_filter: {
1818
plugin: 'accept_fibonacci_numbers',
19-
consumes: 'a',
19+
consumes: { product: 'a', layer: "event" },
2020
max_number: max_number,
2121
},
2222
d: {
2323
plugin: 'verify_even_fibonacci_numbers',
2424
when: ['even_filter:accept_even_numbers', 'fibonacci_filter:accept'],
25-
consumes: 'a',
25+
consumes: { product: 'a', layer: "event" },
2626
max_number: max_number,
2727
},
2828
provider: {

0 commit comments

Comments
 (0)