summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRutger Broekhoff2026-08-28 23:29:00 +0200
committerRutger Broekhoff2026-08-28 23:29:00 +0200
commit35878b76049b9c3e752480e9f298b7e2da6fdf1f (patch)
tree034bd4bcbbd0445e8f3a13dba0b7d517807bbaaa
parentb0d7600970d2fdb1eb6fff813c7336ea34d4e228 (diff)
downloadroutemon-35878b76049b9c3e752480e9f298b7e2da6fdf1f.tar.gz
routemon-35878b76049b9c3e752480e9f298b7e2da6fdf1f.zip
Make RWGPS config optional
-rw-r--r--server/src/config.cpp40
-rw-r--r--server/src/config.cppm6
-rw-r--r--server/src/main.cpp7
-rw-r--r--server/src/srv.cppm3
4 files changed, 35 insertions, 21 deletions
diff --git a/server/src/config.cpp b/server/src/config.cpp
index eab97b5..5c1a161 100644
--- a/server/src/config.cpp
+++ b/server/src/config.cpp
@@ -23,9 +23,9 @@ class location
23 { 23 {
24 if (next_) 24 if (next_)
25 { 25 {
26 next_->second->append_to(s);
26 s += next_->first; 27 s += next_->first;
27 s += "."; 28 s += ".";
28 next_->second->append_to(s);
29 } 29 }
30 } 30 }
31 31
@@ -41,8 +41,9 @@ public:
41 { 41 {
42 if (!next_) 42 if (!next_)
43 return ""; 43 return "";
44 auto s = std::string{next_->first}; 44 auto s = std::string{};
45 next_->second->append_to(s); 45 next_->second->append_to(s);
46 s += next_->first;
46 return s; 47 return s;
47 } 48 }
48 49
@@ -80,11 +81,11 @@ public:
80 } 81 }
81 82
82 template <class T> 83 template <class T>
83 auto expect_at(std::string_view key) -> T 84 auto allow_at(std::string_view key) -> std::optional<T>
84 { 85 {
85 visited_.emplace(key); 86 visited_.emplace(key);
86 auto const loc = loc_.sub(key); 87 auto const loc = loc_.sub(key);
87 if (auto const jv = obj_.try_at(key)) 88 if (auto const jv = obj_.try_at(key); jv && !jv->is_null())
88 { 89 {
89 try 90 try
90 { 91 {
@@ -98,8 +99,21 @@ public:
98 } 99 }
99 else 100 else
100 { 101 {
102 return std::nullopt;
103 }
104 }
105
106 template <class T>
107 auto expect_at(std::string_view key) -> T
108 {
109 if (auto&& mv = allow_at<T>(key); mv)
110 {
111 return std::forward<T>(*mv);
112 }
113 else
114 {
101 throw std::runtime_error{std::format( 115 throw std::runtime_error{std::format(
102 "did not find expected key {}", loc.to_string())}; 116 "did not find expected key {}", loc_.sub(key).to_string())};
103 } 117 }
104 } 118 }
105}; 119};
@@ -124,8 +138,9 @@ auto tag_invoke(
124 [](object_reader& r) -> rwgps 138 [](object_reader& r) -> rwgps
125 { 139 {
126 return { 140 return {
127 .api_key = r.expect_at<std::string>("api_key"), 141 .api_key_filename = r.expect_at<std::string>("api_key_filename"),
128 .auth_token = r.expect_at<std::string>("auth_token"), 142 .auth_token_filename =
143 r.expect_at<std::string>("auth_token_filename"),
129 }; 144 };
130 }); 145 });
131} 146}
@@ -206,7 +221,7 @@ auto json_value_to_app(json::value const& jv) -> app
206 [](object_reader& r) -> app 221 [](object_reader& r) -> app
207 { 222 {
208 return { 223 return {
209 .rwgps = r.expect_at<rwgps>("rwgps"), 224 .rwgps = r.allow_at<rwgps>("rwgps"),
210 .situations = r.expect_at<situations>("situations"), 225 .situations = r.expect_at<situations>("situations"),
211 .database = r.expect_at<database>("database"), 226 .database = r.expect_at<database>("database"),
212 .http_server = r.expect_at<http_server>("http_server"), 227 .http_server = r.expect_at<http_server>("http_server"),
@@ -217,9 +232,12 @@ auto json_value_to_app(json::value const& jv) -> app
217 232
218auto load_file(std::string const& filename) -> app 233auto load_file(std::string const& filename) -> app
219{ 234{
220 auto f = std::ifstream{ 235 // TODO: migrate away from json::value_to w/ tag_invoke.
221 filename 236 // Boost.JSON does not properly propagate custom exceptions accross
222 }; // TODO: ensure that we are opening in binary mode? 237 // json::value_to calls when certain containers are involved
238 // (std::{optional,variant,vector}).
239
240 auto f = std::ifstream{filename, std::ios::binary};
223 if (!f.is_open()) 241 if (!f.is_open())
224 throw std::runtime_error{std::format("failed to open {}", filename)}; 242 throw std::runtime_error{std::format("failed to open {}", filename)};
225 auto jv = json::value{}; 243 auto jv = json::value{};
diff --git a/server/src/config.cppm b/server/src/config.cppm
index e5b48f4..358a961 100644
--- a/server/src/config.cppm
+++ b/server/src/config.cppm
@@ -7,8 +7,8 @@ namespace routemon::config {
7 7
8export struct rwgps 8export struct rwgps
9{ 9{
10 std::string api_key; 10 std::string api_key_filename;
11 std::string auth_token; 11 std::string auth_token_filename;
12}; 12};
13 13
14export struct situations 14export struct situations
@@ -33,7 +33,7 @@ export struct logger
33 33
34export struct app 34export struct app
35{ 35{
36 rwgps rwgps; 36 std::optional<rwgps> rwgps;
37 situations situations; 37 situations situations;
38 database database; 38 database database;
39 http_server http_server; 39 http_server http_server;
diff --git a/server/src/main.cpp b/server/src/main.cpp
index 3f8cb11..d5fcd42 100644
--- a/server/src/main.cpp
+++ b/server/src/main.cpp
@@ -52,13 +52,6 @@ auto real_main(std::span<char const*> args) -> exit_status
52 return exit_status::failure; 52 return exit_status::failure;
53 } 53 }
54 sink->set_level(config.logger.level); 54 sink->set_level(config.logger.level);
55 // auto rwgps_client = routemon::rwgps::client{ioc, l, config.rwgps.api_key,
56 // config.rwgps.auth_token}; for (auto route :
57 // rwgps_client.get_all_routes())
58 // {
59 // l.info("Route {} (user {}): {} @ {}", route.id, route.user_id,
60 // route.name, route.url);
61 // }
62 55
63 auto dbc = std::shared_ptr<routemon::database::connection>{}; 56 auto dbc = std::shared_ptr<routemon::database::connection>{};
64 try 57 try
diff --git a/server/src/srv.cppm b/server/src/srv.cppm
index aef28f4..904bf1a 100644
--- a/server/src/srv.cppm
+++ b/server/src/srv.cppm
@@ -36,17 +36,20 @@ class gpx_parse_error_category_impl : public std::error_category
36{ 36{
37public: 37public:
38 char const* name() const noexcept override { return "gpx_parse"; } 38 char const* name() const noexcept override { return "gpx_parse"; }
39
39 auto message(int condition) const noexcept -> std::string override 40 auto message(int condition) const noexcept -> std::string override
40 { 41 {
41 std::ignore = condition; 42 std::ignore = condition;
42 return "failed to parse GPX file"; 43 return "failed to parse GPX file";
43 } 44 }
44}; 45};
46
45auto gpx_parse_error_category() noexcept -> gpx_parse_error_category_impl const& 47auto gpx_parse_error_category() noexcept -> gpx_parse_error_category_impl const&
46{ 48{
47 static auto const inst = gpx_parse_error_category_impl{}; 49 static auto const inst = gpx_parse_error_category_impl{};
48 return inst; 50 return inst;
49} 51}
52
50auto gpx_parse_error() noexcept -> std::error_code 53auto gpx_parse_error() noexcept -> std::error_code
51{ 54{
52 return std::error_code{1, gpx_parse_error_category()}; 55 return std::error_code{1, gpx_parse_error_category()};