Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues with HTTP subscriptions #356

Merged
merged 4 commits into from
Nov 7, 2024
Merged

Conversation

wirew0rm
Copy link
Member

@wirew0rm wirew0rm commented Nov 6, 2024

This fixes some http subscription issues, the most obvious a latency buildup, whenever the notifiation rate was more than 10Hz. I also noticed that the RestClients did not track the last received LongPollingIdx which makes it impossible for them to catch up or even detect missing updates.

See commit messages for more details.

I'll push a draft PR to opendigitizer based on these changes, which contains a utilitiy to analyze end to end processing latency analysis tools.

Also had to remove some template keywords to get my local emscripten build compiling again.

Modern LLVM errors on this deprected use of the keyword.

Signed-off-by: Alexander Krimm <[email protected]>
Comment on lines -328 to -337
auto redirect_get = [&client](auto url, auto headers) {
for (;;) {
auto result = client.Get(url, headers);
if (!result) return result;

if (result->status >= 300 && result->status < 400) {
url = httplib::detail::decode_url(result.value().get_header_value("location"), true);
} else {
return result;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was not needed, since httplib resolves redirects internally with the set_follow_location(true) setting which is applied above

@@ -393,10 +389,9 @@ class RestBackend : public Mode {
_connectionUpdaterThread = std::jthread([this](std::stop_token stop_token) {
thread::setThreadName("RestBackend updater thread");
while (!stop_token.stop_requested()) {
std::this_thread::sleep_for(100ms);
std::this_thread::sleep_for(10ms);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the actual rate limit of 1/100ms=1Hz on the updates coming from the broker. TBD if it is needed at all or should be even lower/only applied if there are no connections to poll on.

@@ -453,7 +444,7 @@ class RestBackend : public Mode {
if (events & ZMQ_POLLIN) {
auto *currentConnection = connections[i];
auto connectionLock = currentConnection->writeLock();
if (auto responseMessage = zmq::receive<mdp::MessageFormat::WithoutSourceId>(currentConnection->notificationSubscriptionSocket)) {
while (auto responseMessage = zmq::receive<mdp::MessageFormat::WithoutSourceId>(currentConnection->notificationSubscriptionSocket)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change lets the client handle all available notifications for a connection at once, allowing it to catch up. One open question I have here is whether this is safe, as it seems like zmq::receive drops everything already received frames when it cannot get all required frames of a message. Basically the question is if Messages are sent atomically or if we could get partial messages here.

Changes the RestClient to internally track the last received update
index instead of just blindly always requesting the latest update.
This prevents duplicate notifications and allows catching up and
blocking on not yet arrived updates.

For emscripten this needs a bit of trickery because the api of
emscripten_fetch does not provide a way to access the final redirected
URL, so we have to call out to javascript to retrieve it.

Signed-off-by: Alexander Krimm <[email protected]>
The poll loop that handles the messages from the broker had a 100ms
sleep built-in and only handled only one update per iteration and
connection.
This lead to updates being acumulated in the RestBackend's subscription
socket, whenever the underlying property would update with more than
10Hz.

This commit reduces the sleep between poll loops to 10ms and handles all
notifications for all connections at once, allowing the RestBackend to
catch up on a burst of notifications.

smaller changes:
- make http headers case-insensitive
- general code-cleanup

Signed-off-by: Alexander Krimm <[email protected]>
Fix the unittests which do not corretly handle the
LongPollingIdx parameter.

Signed-off-by: Alexander Krimm <[email protected]>
@wirew0rm wirew0rm force-pushed the restClientLongPollingIdx branch from 3f4f431 to 4e1d52e Compare November 7, 2024 15:54
@wirew0rm wirew0rm temporarily deployed to configure coverage November 7, 2024 15:54 — with GitHub Actions Inactive
@wirew0rm wirew0rm temporarily deployed to configure coverage November 7, 2024 15:54 — with GitHub Actions Inactive
@wirew0rm wirew0rm temporarily deployed to configure coverage November 7, 2024 15:54 — with GitHub Actions Inactive
@wirew0rm wirew0rm temporarily deployed to configure coverage November 7, 2024 15:54 — with GitHub Actions Inactive
@wirew0rm wirew0rm temporarily deployed to configure coverage November 7, 2024 15:54 — with GitHub Actions Inactive
@wirew0rm wirew0rm temporarily deployed to configure coverage November 7, 2024 15:54 — with GitHub Actions Inactive
Copy link

sonarqubecloud bot commented Nov 7, 2024

Quality Gate Failed Quality Gate failed

Failed conditions
46.7% Coverage on New Code (required ≥ 80%)

See analysis details on SonarCloud

Copy link
Member

@RalphSteinhagen RalphSteinhagen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work for tracking this down and fixing it. We need to further investigate and reduce the excessive lock durations and unused code. But this is good for now. Well done. 👍

@RalphSteinhagen RalphSteinhagen merged commit 8da3e2f into main Nov 7, 2024
8 of 9 checks passed
@RalphSteinhagen RalphSteinhagen deleted the restClientLongPollingIdx branch November 7, 2024 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants