EventService: Add retry configuration support
This commit is to pass configuration parameters: retry attempts,
retry interval secs and retry policy to http client and take
required delivery retry policy action.
Also, perform async wait for retryTimeoutInterval before each
retry attempts.
Tested:
- Set and verified config properties by sending PATCH req on
EventService and EventDestination uri.
- Verified the appropriate delivery retry policy action block reached.
- Verified the async_wait logic by triggering retry case depending
failed state of connection.
- could see a wait for timeout interval before next retry.
Signed-off-by: Ayushi Smriti <smriti.ayushi@linux.intel.com>
Change-Id: Id1366fca59dc9e6543c553bfe5df95a59f468bc7
Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
diff --git a/http/http_client.hpp b/http/http_client.hpp
index 8b1fb5c..58086dd 100644
--- a/http/http_client.hpp
+++ b/http/http_client.hpp
@@ -42,13 +42,15 @@
recvFailed,
idle,
suspended,
- closed
+ closed,
+ terminated
};
class HttpClient : public std::enable_shared_from_this<HttpClient>
{
private:
boost::beast::tcp_stream conn;
+ boost::asio::steady_timer timer;
boost::beast::flat_buffer buffer;
boost::beast::http::request<boost::beast::http::string_body> req;
boost::beast::http::response<boost::beast::http::string_body> res;
@@ -56,11 +58,15 @@
std::vector<std::pair<std::string, std::string>> headers;
std::queue<std::string> requestDataQueue;
ConnState state;
+ std::string subId;
std::string host;
std::string port;
std::string uri;
- int retryCount;
- int maxRetryAttempts;
+ uint32_t retryCount;
+ uint32_t maxRetryAttempts;
+ uint32_t retryIntervalSecs;
+ std::string retryPolicyAction;
+ bool runningTimer;
void doConnect()
{
@@ -208,10 +214,23 @@
requestDataQueue.pop();
}
- // TODO: Take 'DeliveryRetryPolicy' action.
- // For now, doing 'SuspendRetries' action.
- state = ConnState::suspended;
- return;
+ BMCWEB_LOG_DEBUG << "Retry policy is set to " << retryPolicyAction;
+ if (retryPolicyAction == "TerminateAfterRetries")
+ {
+ // TODO: delete subscription
+ state = ConnState::terminated;
+ return;
+ }
+ else if (retryPolicyAction == "SuspendRetries")
+ {
+ state = ConnState::suspended;
+ return;
+ }
+ else
+ {
+ // keep retrying, reset count and continue.
+ retryCount = 0;
+ }
}
if ((state == ConnState::connectFailed) ||
@@ -226,20 +245,43 @@
return;
}
+ if (runningTimer)
+ {
+ BMCWEB_LOG_DEBUG << "Retry timer is already running.";
+ return;
+ }
+ runningTimer = true;
+
retryCount++;
- // TODO: Perform async wait for retryTimeoutInterval before proceed.
+
+ BMCWEB_LOG_DEBUG << "Attempt retry after " << retryIntervalSecs
+ << " seconds. RetryCount = " << retryCount;
+ timer.expires_after(std::chrono::seconds(retryIntervalSecs));
+ timer.async_wait([self = shared_from_this()](
+ const boost::system::error_code& ec) {
+ self->runningTimer = false;
+ self->connStateCheck();
+ });
+ return;
}
else
{
// reset retry count.
retryCount = 0;
}
+ connStateCheck();
+ return;
+ }
+
+ void connStateCheck()
+ {
switch (state)
{
case ConnState::connectInProgress:
case ConnState::sendInProgress:
case ConnState::suspended:
+ case ConnState::terminated:
// do nothing
break;
case ConnState::initialized:
@@ -263,22 +305,20 @@
default:
break;
}
-
- return;
}
public:
- explicit HttpClient(boost::asio::io_context& ioc, const std::string& destIP,
- const std::string& destPort,
+ explicit HttpClient(boost::asio::io_context& ioc, const std::string& id,
+ const std::string& destIP, const std::string& destPort,
const std::string& destUri) :
conn(ioc),
- host(destIP), port(destPort), uri(destUri)
+ timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri),
+ retryCount(0), maxRetryAttempts(5),
+ retryPolicyAction("TerminateAfterRetries"), runningTimer(false)
{
boost::asio::ip::tcp::resolver resolver(ioc);
endpoint = resolver.resolve(host, port);
state = ConnState::initialized;
- retryCount = 0;
- maxRetryAttempts = 5;
}
void sendData(const std::string& data)
@@ -306,6 +346,18 @@
{
headers = httpHeaders;
}
+
+ void setRetryConfig(const uint32_t retryAttempts,
+ const uint32_t retryTimeoutInterval)
+ {
+ maxRetryAttempts = retryAttempts;
+ retryIntervalSecs = retryTimeoutInterval;
+ }
+
+ void setRetryPolicy(const std::string& retryPolicy)
+ {
+ retryPolicyAction = retryPolicy;
+ }
};
} // namespace crow
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
index c11e31b..7c96420 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -292,7 +292,8 @@
host(inHost), port(inPort), path(inPath), uriProto(inUriProto)
{
conn = std::make_shared<crow::HttpClient>(
- crow::connections::systemBus->get_io_context(), host, port, path);
+ crow::connections::systemBus->get_io_context(), id, host, port,
+ path);
}
~Subscription()
{}
@@ -444,6 +445,17 @@
this->sendEvent(msg.dump());
}
+ void updateRetryConfig(const uint32_t retryAttempts,
+ const uint32_t retryTimeoutInterval)
+ {
+ conn->setRetryConfig(retryAttempts, retryTimeoutInterval);
+ }
+
+ void updateRetryPolicy()
+ {
+ conn->setRetryPolicy(retryPolicy);
+ }
+
private:
uint64_t eventSeqNum;
std::string host;
@@ -677,6 +689,7 @@
void setEventServiceConfig(const EventServiceConfig& cfg)
{
bool updateConfig = false;
+ bool updateRetryCfg = false;
if (serviceEnabled != std::get<0>(cfg))
{
@@ -696,18 +709,31 @@
{
retryAttempts = std::get<1>(cfg);
updateConfig = true;
+ updateRetryCfg = true;
}
if (retryTimeoutInterval != std::get<2>(cfg))
{
retryTimeoutInterval = std::get<2>(cfg);
updateConfig = true;
+ updateRetryCfg = true;
}
if (updateConfig)
{
updateSubscriptionData();
}
+
+ if (updateRetryCfg)
+ {
+ // Update the changed retry config to all subscriptions
+ for (const auto& it :
+ EventServiceManager::getInstance().subscriptionsMap)
+ {
+ std::shared_ptr<Subscription> entry = it.second;
+ entry->updateRetryConfig(retryAttempts, retryTimeoutInterval);
+ }
+ }
}
void updateNoOfSubscribersCount()
@@ -791,6 +817,10 @@
cacheLastEventTimestamp();
}
#endif
+ // Update retry configuration.
+ subValue->updateRetryConfig(retryAttempts, retryTimeoutInterval);
+ subValue->updateRetryPolicy();
+
return id;
}
diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
index b88cb43..ba1ea19 100644
--- a/redfish-core/lib/event_service.hpp
+++ b/redfish-core/lib/event_service.hpp
@@ -507,6 +507,7 @@
return;
}
subValue->retryPolicy = *retryPolicy;
+ subValue->updateRetryPolicy();
}
EventServiceManager::getInstance().updateSubscriptionData();