Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 212 additions & 0 deletions lib/base/io-future.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/* Icinga 2 | (c) 2025 Icinga GmbH | GPLv2+ */

#pragma once

#include "base/application.hpp"
#include "base/shared-object.hpp"
#include "base/threadpool.hpp"
#include <boost/asio/dispatch.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/spawn.hpp>
#include <future>

namespace boost::asio::detail {

struct fixed_throw_tag
{};

/**
* Fixes the issue where operations crash the program that can throw exceptions but don't.
*
* The issues is that in the orginal version of this specialization, the exception_ptr is
* never checked against nullptr, but only the pointer to the exception_ptr, which is likely
* a mistake.
*/
template<typename Executor, typename R, typename T>
class spawn_handler<Executor, R(std::exception_ptr, T, fixed_throw_tag)> : public spawn_handler_base<Executor>

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2

'spawn_handler' is not a class template

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2023

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2023

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2023

'spawn_handler' is not a class template

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:11

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:11

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:11

'spawn_handler' is not a class template

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:12

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:12

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:12

'spawn_handler' is not a class template

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / opensuse/leap:15.6

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / opensuse/leap:15.6

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / opensuse/leap:15.6

'spawn_handler' is not a class template

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:8

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:8

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:8

'spawn_handler' is not a class template

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:9

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:9

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:9

'spawn_handler' is not a class template

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.6

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.6

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.6

'spawn_handler' is not a class template

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.7

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.7

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.7

'spawn_handler' is not a class template

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04

'spawn_handler' is not a class template

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:11 (linux/386)

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:11 (linux/386)

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:11 (linux/386)

'spawn_handler' is not a class template

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:12 (linux/386)

expected '{' before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:12 (linux/386)

expected template-name before '<' token

Check failure on line 26 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:12 (linux/386)

'spawn_handler' is not a class template
{
public:
using return_type = T;

struct result_type
{
std::exception_ptr ex_;
return_type* value_;
};

spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)
: spawn_handler_base<Executor>(yield), result_(result)
{
}

void operator()(std::exception_ptr ex, T value)
{
result_.ex_ = ex;
result_.value_ = &value;
this->resume();
}

static return_type on_resume(result_type& result)
{
if (result.ex_) {
rethrow_exception(result.ex_);
}
return BOOST_ASIO_MOVE_CAST(return_type)(*result.value_);
}

private:
result_type& result_;
};

} // namespace boost::asio::detail

namespace icinga {

template<typename>
class AsioPromise;

/**
* Implements a generic, asynchronously awaitable future.
*
* This allows to queue an CPU-intensive action on another thread without blocking any
* IO-threads and pass back the result via the @c AsioPromise.
*
* Similar to @c std::future, this is single-use only. Once a value has been set by the
* @c AsioPromise, the job is done.
*/
template<typename ValueType>
class AsioFuture : public SharedObject
{
template<typename>
friend class AsioPromise;

public:
DECLARE_PTR_TYPEDEFS(AsioFuture);

/**
* Returns the value held in the future, or waits for the promise to complete.
*
* If an exception has been stored in the future via AsioPromise::SetException(), it will be
* thrown by this function. Simply passing `yc[ec]` as a token will not change this, even if
* the exception that would be thrown is a @c boost::asio::system::system_error.
*/
template<typename CompletionToken>
auto Get(CompletionToken&& token)
{
using Signature = void(std::exception_ptr, ValueType, boost::asio::detail::fixed_throw_tag);

return boost::asio::async_initiate<CompletionToken, Signature>(

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2

expected primary-expression before '>' token

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2

expected primary-expression before ',' token

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2

'async_initiate' is not a member of 'boost::asio'

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / opensuse/leap:15.6

expected primary-expression before '>' token

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / opensuse/leap:15.6

expected primary-expression before ',' token

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / opensuse/leap:15.6

'async_initiate' is not a member of 'boost::asio'

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:8

expected primary-expression before '>' token

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:8

expected primary-expression before ',' token

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:8

'async_initiate' is not a member of 'boost::asio'

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.6

expected primary-expression before '>' token

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.6

expected primary-expression before ',' token

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.6

'async_initiate' is not a member of 'boost::asio'

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.7

expected primary-expression before '>' token

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.7

expected primary-expression before ',' token

Check failure on line 98 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.7

'async_initiate' is not a member of 'boost::asio'
[this](auto&& handler) { InitOperation(std::forward<decltype(handler)>(handler)); },
std::forward<CompletionToken>(token)
);
}

// TODO: Add WaitFor and WaitUntil

private:
template<typename Handler>
void CallHandler(Handler&& handler)
{
if (std::holds_alternative<ValueType>(m_Value)) {

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / opensuse/leap:15.6

'm_Value' was not declared in this scope

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / opensuse/leap:15.6

expected primary-expression before '>' token

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / opensuse/leap:15.6

'holds_alternative' is not a member of 'std'

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:8

'm_Value' was not declared in this scope

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:8

expected primary-expression before '>' token

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:8

'holds_alternative' is not a member of 'std'

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.6

'm_Value' was not declared in this scope

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.6

expected primary-expression before '>' token

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.6

'holds_alternative' is not a member of 'std'

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.7

'm_Value' was not declared in this scope

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.7

expected primary-expression before '>' token

Check failure on line 110 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.7

'holds_alternative' is not a member of 'std'
std::forward<Handler>(handler)(nullptr, std::get<ValueType>(m_Value));
} else {
std::forward<Handler>(handler)(std::get<std::exception_ptr>(m_Value), {});
}
}

template<typename Handler>
void InitOperation(Handler&& handler)
{
auto handlerPtr = std::make_shared<std::decay_t<decltype(handler)>>(std::forward<decltype(handler)>(handler));

auto handlerWrapper = [handler = handlerPtr, future = AsioFuture::Ptr{this}]() {
if (std::holds_alternative<ValueType>(future->m_Value)) {
(*handler)({}, std::get<ValueType>(future->m_Value));

Check failure on line 124 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2023

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (<brace-enclosed initializer list>, bool&)'

Check failure on line 124 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:11

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (<brace-enclosed initializer list>, bool&)'

Check failure on line 124 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:12

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (<brace-enclosed initializer list>, bool&)'

Check failure on line 124 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:9

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (<brace-enclosed initializer list>, bool&)'

Check failure on line 124 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (<brace-enclosed initializer list>, bool&)'

Check failure on line 124 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:11 (linux/386)

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (<brace-enclosed initializer list>, bool&)'

Check failure on line 124 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:12 (linux/386)

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (<brace-enclosed initializer list>, bool&)'
} else {
(*handler)(std::get<std::exception_ptr>(future->m_Value), {});

Check failure on line 126 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2023

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (std::__exception_ptr::exception_ptr&, <brace-enclosed initializer list>)'

Check failure on line 126 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:11

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (std::__exception_ptr::exception_ptr&, <brace-enclosed initializer list>)'

Check failure on line 126 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:12

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (std::__exception_ptr::exception_ptr&, <brace-enclosed initializer list>)'

Check failure on line 126 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:9

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (std::__exception_ptr::exception_ptr&, <brace-enclosed initializer list>)'

Check failure on line 126 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (std::__exception_ptr::exception_ptr&, <brace-enclosed initializer list>)'

Check failure on line 126 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:11 (linux/386)

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (std::__exception_ptr::exception_ptr&, <brace-enclosed initializer list>)'

Check failure on line 126 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / debian:12 (linux/386)

no match for call to '(std::__shared_ptr_access<boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >, __gnu_cxx::_S_atomic, false, false>::element_type {aka boost::asio::basic_yield_context<boost::asio::executor_binder<void (*)(), boost::asio::executor> >}) (std::__exception_ptr::exception_ptr&, <brace-enclosed initializer list>)'
}
};

std::unique_lock lock(m_Mutex);

if (!std::holds_alternative<std::monostate>(m_Value)) {
boost::asio::post(boost::asio::get_associated_executor(handler), handlerWrapper);
return;
}

auto work = boost::asio::make_work_guard(handler);
m_Callback = [handler = std::move(handlerWrapper), work = std::move(work)]() mutable {
boost::asio::dispatch(work.get_executor(), handler);
work.reset();
};
}

std::mutex m_Mutex;
std::variant<std::monostate, std::exception_ptr, ValueType> m_Value;

Check failure on line 145 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / opensuse/leap:15.6

'variant' in namespace 'std' does not name a template type

Check failure on line 145 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / rockylinux:8

'variant' in namespace 'std' does not name a template type

Check failure on line 145 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.6

'variant' in namespace 'std' does not name a template type

Check failure on line 145 in lib/base/io-future.hpp

View workflow job for this annotation

GitHub Actions / registry.suse.com/suse/sle15:15.7

'variant' in namespace 'std' does not name a template type
std::function<void()> m_Callback;
};

/**
* A promise type that can be passed to any other thread or coroutine.
*/
template<typename ValueType>
class AsioPromise
{
public:
AsioPromise() : m_Future(new AsioFuture<ValueType>) {}

template<typename ForwardingType>
void SetValue(ForwardingType&& value) const
{
std::unique_lock lock{m_Future->m_Mutex};

if (!std::holds_alternative<std::monostate>(m_Future->m_Value)) {
BOOST_THROW_EXCEPTION(std::future_error{std::future_errc::promise_already_satisfied});
}

m_Future->m_Value = std::forward<ForwardingType>(value);
if (m_Future->m_Callback) {
m_Future->m_Callback();
}
}

template<typename ExceptionType>
void SetException(ExceptionType&& ex) const
{
std::unique_lock lock{m_Future->m_Mutex};

if (!std::holds_alternative<std::monostate>(m_Future->m_Value)) {
BOOST_THROW_EXCEPTION(std::future_error{std::future_errc::promise_already_satisfied});
}

m_Future->m_Value = std::make_exception_ptr(std::forward<ExceptionType>(ex));
if (m_Future->m_Callback) {
m_Future->m_Callback();
}
}

auto GetFuture() const { return m_Future; }

private:
typename AsioFuture<ValueType>::Ptr m_Future;
};

template<typename Callback>
auto QueueAsioFutureCallback(Callback&& cb)
{
AsioPromise<decltype(cb())> promise;
auto future = promise.GetFuture();
Application::GetTP().Post(
[cb = std::forward<Callback>(cb), promise = std::move(promise)]() {
try {
promise.SetValue(cb());
} catch (const std::exception&) {
promise.SetException(std::current_exception());
}
},
{}
);
return future;
};

} // namespace icinga
37 changes: 20 additions & 17 deletions lib/remote/configpackageshandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "remote/httputility.hpp"
#include "remote/filterutility.hpp"
#include "base/exception.hpp"
#include "base/io-future.hpp"

using namespace icinga;

Expand All @@ -20,23 +21,25 @@
{
namespace http = boost::beast::http;

auto url = request.Url();
auto user = request.User();
auto params = request.Params();

if (url->GetPath().size() > 4)
return false;

if (request.method() == http::verb::get)
HandleGet(request, response);
else if (request.method() == http::verb::post)
HandlePost(request, response);
else if (request.method() == http::verb::delete_)
HandleDelete(request, response);
else
return false;

return true;
return QueueAsioFutureCallback([&]() {
auto url = request.Url();
auto user = request.User();
auto params = request.Params();

if (url->GetPath().size() > 4)
return false;

if (request.method() == http::verb::get)
HandleGet(request, response);
else if (request.method() == http::verb::post)
HandlePost(request, response);
else if (request.method() == http::verb::delete_)
HandleDelete(request, response);
else
return false;
Copy link
Member

Choose a reason for hiding this comment

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

What about wrapping at the Handle*() level? I mean, what a waste to deploy a callback which will almost immediately return false..

Copy link
Contributor Author

@jschmidt-icinga jschmidt-icinga Nov 7, 2025

Choose a reason for hiding this comment

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

Absolutely. That's why I put an extra (WIP) in front of the second commit. It was just thrown together quickly to test if it even works. I'm sure it can be made a lot nicer by applying the callbacks more selectively.


return true;
})->Get(yc);

Check failure on line 42 in lib/remote/configpackageshandler.cpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2

void value not ignored as it ought to be

Check failure on line 42 in lib/remote/configpackageshandler.cpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2023

void value not ignored as it ought to be

Check failure on line 42 in lib/remote/configpackageshandler.cpp

View workflow job for this annotation

GitHub Actions / debian:11

void value not ignored as it ought to be

Check failure on line 42 in lib/remote/configpackageshandler.cpp

View workflow job for this annotation

GitHub Actions / debian:12

void value not ignored as it ought to be

Check failure on line 42 in lib/remote/configpackageshandler.cpp

View workflow job for this annotation

GitHub Actions / rockylinux:9

void value not ignored as it ought to be

Check failure on line 42 in lib/remote/configpackageshandler.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04

void value not ignored as it ought to be

Check failure on line 42 in lib/remote/configpackageshandler.cpp

View workflow job for this annotation

GitHub Actions / debian:11 (linux/386)

void value not ignored as it ought to be

Check failure on line 42 in lib/remote/configpackageshandler.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (linux/386)

void value not ignored as it ought to be
}

void ConfigPackagesHandler::HandleGet(const HttpRequest& request, HttpResponse& response)
Expand Down
33 changes: 19 additions & 14 deletions lib/remote/configstageshandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "base/application.hpp"
#include "base/defer.hpp"
#include "base/exception.hpp"
#include "base/io-future.hpp"

using namespace icinga;

Expand All @@ -27,23 +28,27 @@
{
namespace http = boost::beast::http;

auto url = request.Url();
auto user = request.User();
auto params = request.Params();
auto future = QueueAsioFutureCallback([&]() {
auto url = request.Url();
auto user = request.User();
auto params = request.Params();

if (url->GetPath().size() > 5)
return false;
if (url->GetPath().size() > 5)
return false;

if (request.method() == http::verb::get)
HandleGet(request, response);
else if (request.method() == http::verb::post)
HandlePost(request, response);
else if (request.method() == http::verb::delete_)
HandleDelete(request, response);
else
return false;
if (request.method() == http::verb::get)
HandleGet(request, response);
else if (request.method() == http::verb::post)
HandlePost(request, response);
else if (request.method() == http::verb::delete_)
HandleDelete(request, response);
else
return false;

return true;
});

return true;
return future->Get(yc);

Check failure on line 51 in lib/remote/configstageshandler.cpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2

void value not ignored as it ought to be

Check failure on line 51 in lib/remote/configstageshandler.cpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2023

void value not ignored as it ought to be

Check failure on line 51 in lib/remote/configstageshandler.cpp

View workflow job for this annotation

GitHub Actions / debian:11

void value not ignored as it ought to be

Check failure on line 51 in lib/remote/configstageshandler.cpp

View workflow job for this annotation

GitHub Actions / debian:12

void value not ignored as it ought to be

Check failure on line 51 in lib/remote/configstageshandler.cpp

View workflow job for this annotation

GitHub Actions / rockylinux:9

void value not ignored as it ought to be

Check failure on line 51 in lib/remote/configstageshandler.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04

void value not ignored as it ought to be

Check failure on line 51 in lib/remote/configstageshandler.cpp

View workflow job for this annotation

GitHub Actions / debian:11 (linux/386)

void value not ignored as it ought to be

Check failure on line 51 in lib/remote/configstageshandler.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (linux/386)

void value not ignored as it ought to be
}

void ConfigStagesHandler::HandleGet(const HttpRequest& request, HttpResponse& response)
Expand Down
18 changes: 15 additions & 3 deletions lib/remote/createobjecthandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
#include "remote/apiaction.hpp"
#include "remote/zone.hpp"
#include "base/configtype.hpp"
#include "base/io-future.hpp"
#include <set>

using namespace icinga;

REGISTER_URLHANDLER("/v1/objects", CreateObjectHandler);

bool CreateObjectHandler::HandleRequest(
static bool HandleRequestImpl(
const WaitGroup::Ptr& waitGroup,
const HttpRequest& request,
HttpResponse& response,
boost::asio::yield_context& yc
HttpResponse& response
)
{
namespace http = boost::beast::http;
Expand Down Expand Up @@ -162,3 +162,15 @@

return true;
}

bool CreateObjectHandler::HandleRequest(
const WaitGroup::Ptr& waitGroup,
const HttpRequest& request,
HttpResponse& response,
boost::asio::yield_context& yc
)
{
return QueueAsioFutureCallback([&](){
return HandleRequestImpl(waitGroup, request, response);
})->Get(yc);

Check failure on line 175 in lib/remote/createobjecthandler.cpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2

void value not ignored as it ought to be

Check failure on line 175 in lib/remote/createobjecthandler.cpp

View workflow job for this annotation

GitHub Actions / amazonlinux:2023

void value not ignored as it ought to be

Check failure on line 175 in lib/remote/createobjecthandler.cpp

View workflow job for this annotation

GitHub Actions / debian:11

void value not ignored as it ought to be

Check failure on line 175 in lib/remote/createobjecthandler.cpp

View workflow job for this annotation

GitHub Actions / debian:12

void value not ignored as it ought to be

Check failure on line 175 in lib/remote/createobjecthandler.cpp

View workflow job for this annotation

GitHub Actions / rockylinux:9

void value not ignored as it ought to be

Check failure on line 175 in lib/remote/createobjecthandler.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04

void value not ignored as it ought to be

Check failure on line 175 in lib/remote/createobjecthandler.cpp

View workflow job for this annotation

GitHub Actions / debian:11 (linux/386)

void value not ignored as it ought to be

Check failure on line 175 in lib/remote/createobjecthandler.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (linux/386)

void value not ignored as it ought to be
}
Loading
Loading