Add and test TryMakeFetcher, TryMakeSender, and NodeHasTag helpers
Using a Fetcher for a channel on nodes where it exists and triggering
logic to handle other nodes based on whether the fetcher is valid works
well for some use cases. Add a method to EventLoop to support that
directly, instead of forcing the caller to redo the logic around whether
a channel exists and is readable. Basing similar logic off whether the
node has a given tag is also fairly common.
In the process, fill out the EventLoop tests around channels that don't
exist or aren't readable/writable a bit better.
Change-Id: I168e3c1e98adc4461a01d98360f0f0a78d24bbb5
Signed-off-by: Brian Silverman <brian.silverman@bluerivertech.com>
diff --git a/aos/events/event_loop.h b/aos/events/event_loop.h
index 6f51fb0..42489e5 100644
--- a/aos/events/event_loop.h
+++ b/aos/events/event_loop.h
@@ -517,31 +517,62 @@
return GetChannel<T>(channel_name) != nullptr;
}
+ // Like MakeFetcher, but returns an invalid fetcher if the given channel is
+ // not readable on this node or does not exist.
+ template <typename T>
+ Fetcher<T> TryMakeFetcher(const std::string_view channel_name) {
+ const Channel *const channel = GetChannel<T>(channel_name);
+ if (channel == nullptr) {
+ return Fetcher<T>();
+ }
+
+ if (!configuration::ChannelIsReadableOnNode(channel, node())) {
+ return Fetcher<T>();
+ }
+
+ return Fetcher<T>(MakeRawFetcher(channel));
+ }
+
// Makes a class that will always fetch the most recent value
// sent to the provided channel.
template <typename T>
Fetcher<T> MakeFetcher(const std::string_view channel_name) {
- const Channel *channel = GetChannel<T>(channel_name);
- CHECK(channel != nullptr)
+ CHECK(HasChannel<T>(channel_name))
<< ": Channel { \"name\": \"" << channel_name << "\", \"type\": \""
<< T::GetFullyQualifiedName() << "\" } not found in config.";
- if (!configuration::ChannelIsReadableOnNode(channel, node())) {
+ Fetcher<T> result = TryMakeFetcher<T>(channel_name);
+ if (!result.valid()) {
LOG(FATAL) << "Channel { \"name\": \"" << channel_name
<< "\", \"type\": \"" << T::GetFullyQualifiedName()
<< "\" } is not able to be fetched on this node. Check your "
"configuration.";
}
- return Fetcher<T>(MakeRawFetcher(channel));
+ return result;
+ }
+
+ // Like MakeSender, but returns an invalid sender if the given channel is
+ // not readable on this node or does not exist.
+ template <typename T>
+ Sender<T> TryMakeSender(const std::string_view channel_name) {
+ const Channel *channel = GetChannel<T>(channel_name);
+ if (channel == nullptr) {
+ return Sender<T>();
+ }
+
+ if (!configuration::ChannelIsSendableOnNode(channel, node())) {
+ return Sender<T>();
+ }
+
+ return Sender<T>(MakeRawSender(channel));
}
// Makes class that allows constructing and sending messages to
// the provided channel.
template <typename T>
Sender<T> MakeSender(const std::string_view channel_name) {
- const Channel *channel = GetChannel<T>(channel_name);
- CHECK(channel != nullptr)
+ CHECK(HasChannel<T>(channel_name))
<< ": Channel { \"name\": \"" << channel_name << "\", \"type\": \""
<< T::GetFullyQualifiedName() << "\" } not found in config for "
<< name()
@@ -549,14 +580,15 @@
? absl::StrCat(" on node ", node()->name()->string_view())
: ".");
- if (!configuration::ChannelIsSendableOnNode(channel, node())) {
+ Sender<T> result = TryMakeSender<T>(channel_name);
+ if (!result) {
LOG(FATAL) << "Channel { \"name\": \"" << channel_name
<< "\", \"type\": \"" << T::GetFullyQualifiedName()
<< "\" } is not able to be sent on this node. Check your "
"configuration.";
}
- return Sender<T>(MakeRawSender(channel));
+ return result;
}
// This will watch messages sent to the provided channel.