Timer-based asynchronous connection status checker using HTTP requests.
CAsyncConnectionCheckerComp implements IConnectionStatusProvider using a timer-driven approach that periodically sends HTTP requests to verify network connectivity. It provides non-blocking health checks with configurable intervals, timeouts, and retry logic.
This component is ideal for periodic server availability monitoring, network connectivity validation, and health checking scenarios where you need to detect when a server becomes unreachable or recovers.
Key Features
Timer-Based Checking:
- Periodic health checks via QTimer
- Configurable check interval (default: 60 seconds)
- Non-blocking asynchronous requests
- Automatic retry on failure
HTTP-Based Validation:
- Uses QNetworkAccessManager for HTTP requests
- Supports both HTTP and HTTPS endpoints
- Timeout detection
- Connection error handling
Status Management:
- Three states: CS_UNKNOWN, CS_DISCONNECTED, CS_CONNECTED
- Observable status changes via IChangeable
- Initial state: CS_UNKNOWN
- Transitions only when status actually changes
URL Configuration:
- Supports direct URL specification
- Integration with IUrlParam for dynamic URL management
- Server prefix support for URL construction
Architecture
|
+-------------------------+
| |
v v
QTimer QNetworkAccessManager
(periodic trigger) (HTTP request execution)
| |
v v
OnTimeout() ReplyFinished()
| |
v v
SendRequest() Update m_status
| |
+------------+------------+
|
v
Notify IChangeable observers
(only if status changed)
Timer-based asynchronous connection status checker using HTTP requests.
Component Attributes
| Attribute | Type | Description | Default | Required |
| CheckInterval | int | Health check interval in seconds | 60 | No |
| UrlParam | IUrlParam | URL parameter provider for target endpoint | "UrlParam" | No |
| ServerPrefix | QByteArray | Server prefix for URL construction | "ServerPrefix" | Yes |
Component Lifecycle
- OnComponentCreated(): Initializes QNetworkAccessManager and starts timer
- Timer Triggers: Calls OnTimeout() at configured intervals
- SendRequest(): Initiates HTTP GET request to target URL
- ReplyFinished(): Processes response and updates status
- SetStatus(): Updates status and notifies observers if changed
- OnComponentDestroyed(): Stops timer and cleans up network manager
Status Determination Logic
CS_CONNECTED:
- HTTP response received (any status code)
- Network accessible
- DNS resolution successful
CS_DISCONNECTED:
- Network timeout
- Connection refused
- DNS resolution failure
- Network error (no internet, host unreachable, etc.)
CS_UNKNOWN:
- Initial state before first check
- After component reset
Usage Examples
Basic Usage
auto checker = icomp::CreateComponent<CAsyncConnectionCheckerComp>();
checker->SetAttributeValue("CheckInterval", 30);
auto urlParam = icomp::CreateComponent<imtbase::CUrlParamComp>();
urlParam->SetUrl(QUrl("https://api.example.com/health"));
checker->SetReference("UrlParam", urlParam);
QObject::connect(checker.get(), &IChangeable::OnChanged,
[checker](const IChangeable::ChangeSet&) {
auto status = checker->GetConnectionStatus();
if (status == IConnectionStatusProvider::CS_CONNECTED) {
qDebug() << "Server is reachable";
qWarning() << "Server is unreachable";
}
});
@ CS_DISCONNECTED
Connection is unavailable or failed health check.
Health Endpoint Monitoring
class ServerHealthMonitor : public QObject {
Q_OBJECT
public:
ServerHealthMonitor(const QUrl& healthEndpoint) {
m_checker = icomp::CreateComponent<CAsyncConnectionCheckerComp>();
m_checker->SetAttributeValue("CheckInterval", 10);
auto urlParam = icomp::CreateComponent<imtbase::CUrlParamComp>();
urlParam->SetUrl(healthEndpoint);
m_checker->SetReference("UrlParam", urlParam);
connect(m_checker.get(), &IChangeable::OnChanged,
this, &ServerHealthMonitor::OnStatusChanged);
m_consecutiveFailures = 0;
m_lastUptime = QDateTime::currentDateTime();
}
signals:
void serverDown();
void serverUp();
void alertThresholdExceeded(int failureCount);
private slots:
void OnStatusChanged() {
auto status = m_checker->GetConnectionStatus();
if (status == IConnectionStatusProvider::CS_CONNECTED) {
if (m_consecutiveFailures > 0) {
qInfo() << "Server recovered after"
<< m_consecutiveFailures << "failures";
emit serverUp();
}
m_consecutiveFailures = 0;
m_lastUptime = QDateTime::currentDateTime();
} else if (status == IConnectionStatusProvider::CS_DISCONNECTED) {
m_consecutiveFailures++;
if (m_consecutiveFailures == 1) {
qWarning() << "Server health check failed";
emit serverDown();
} else if (m_consecutiveFailures == 3) {
qCritical() << "Server down for" << m_consecutiveFailures
<< "consecutive checks";
emit alertThresholdExceeded(m_consecutiveFailures);
}
}
}
private:
std::shared_ptr<CAsyncConnectionCheckerComp> m_checker;
int m_consecutiveFailures;
QDateTime m_lastUptime;
};
Multi-Server Monitoring
class MultiServerMonitor : public QObject {
Q_OBJECT
public:
void AddServer(const QString& name, const QUrl& url) {
auto checker = icomp::CreateComponent<CAsyncConnectionCheckerComp>();
checker->SetAttributeValue("CheckInterval", 30);
auto urlParam = icomp::CreateComponent<imtbase::CUrlParamComp>();
urlParam->SetUrl(url);
checker->SetReference("UrlParam", urlParam);
connect(checker.get(), &IChangeable::OnChanged,
[this, name, checker]() {
OnServerStatusChanged(name, checker->GetConnectionStatus());
});
m_checkers[name] = checker;
m_status[name] = IConnectionStatusProvider::CS_UNKNOWN;
}
QStringList GetOnlineServers() const {
QStringList online;
for (auto it = m_status.begin(); it != m_status.end(); ++it) {
if (it.value() == IConnectionStatusProvider::CS_CONNECTED) {
online << it.key();
}
}
return online;
}
int GetHealthyServerCount() const {
return GetOnlineServers().size();
}
signals:
void serverStatusChanged(const QString& serverName,
IConnectionStatusProvider::ConnectionStatus status);
private:
void OnServerStatusChanged(const QString& name,
IConnectionStatusProvider::ConnectionStatus status) {
if (m_status[name] != status) {
m_status[name] = status;
QString statusStr = (status == IConnectionStatusProvider::CS_CONNECTED)
? "ONLINE" : "OFFLINE";
qInfo() << "Server" << name << "is now" << statusStr;
emit serverStatusChanged(name, status);
}
}
QMap<QString, std::shared_ptr<CAsyncConnectionCheckerComp>> m_checkers;
QMap<QString, IConnectionStatusProvider::ConnectionStatus> m_status;
};
Best Practices
- Check Intervals: Balance responsiveness and resource usage
- Critical services: 5-10 seconds
- Normal monitoring: 30-60 seconds
- Background checks: 120+ seconds
- Timeout Handling: Network timeouts are detected by QNetworkAccessManager
- Default Qt timeout: 30 seconds
- Configure shorter timeouts for faster failure detection
- Resource Management: Component automatically cleans up on destruction
- Timer stopped in OnComponentDestroyed()
- QNetworkAccessManager deleted
- No manual cleanup required
- Status Notifications: Only fires IChangeable::OnChanged when status changes
- Reduces unnecessary event processing
- Use for reactive UI updates
- URL Configuration: Use IUrlParam for dynamic URL changes
- Allows runtime reconfiguration
- Supports URL updates without recreating component
- Health Endpoints: Design dedicated health check endpoints
- Lightweight responses
- Quick processing
- Return 200 OK if healthy
- Don't require authentication if possible
Troubleshooting
Status Always CS_DISCONNECTED:
- Check URL is correct and reachable
- Verify network connectivity
- Check firewall settings
- Ensure DNS resolution works
- Review QNetworkAccessManager logs
Status Never Updates:
- Verify timer is started (check CheckInterval attribute)
- Ensure OnComponentCreated() was called
- Check UrlParam reference is set
- Verify component is not destroyed prematurely
False Negatives (Shows Disconnected When Online):
- Increase timeout settings
- Check for intermittent network issues
- Verify server response time is reasonable
- Review network request logs
- See also
- IConnectionStatusProvider, CSimpleConnectionCheckerComp, CInternetConnectionCheckerComp
-
imtbase::IUrlParam, QNetworkAccessManager, QTimer
Definition at line 338 of file CAsyncConnectionCheckerComp.h.