Warrior_EA/System/RetryWithBackoff.mqh

49 lines
2.4 KiB
MQL5
Raw Permalink Normal View History

//+------------------------------------------------------------------+
//| Warrior_EA |
//| AnimateDread |
//| |
//| The exponential-backoff retry SHAPE, shared by every call site |
//| that retries one transient-lock-prone operation a fixed number |
//| of times with an increasing, capped sleep between attempts. Each |
//| operation's own arguments differ (a file copy vs a model load), |
//| so the shape is factored out behind a tiny callback interface |
//| instead of a raw function pointer - MQL5 has no closures, and |
//| a function pointer cannot bind the per-call-site arguments. |
//+------------------------------------------------------------------+
#ifndef WARRIOR_RETRY_WITH_BACKOFF_MQH
#define WARRIOR_RETRY_WITH_BACKOFF_MQH
//+------------------------------------------------------------------+
//| One retryable attempt. quiet is true on every attempt but the |
//| last, so an implementation that logs its own per-attempt reason |
//| can stay silent until the failure actually matters. |
//+------------------------------------------------------------------+
class IRetryableOp
{
public:
virtual bool TryOnce(bool quiet) = 0;
};
//+------------------------------------------------------------------+
//| Runs op.TryOnce() up to retryAttempts times, sleeping delayMs |
//| (doubled each attempt, capped at delayCapMs) between attempts. |
//| Returns the first successful attempt's result, or false if every |
//| attempt failed. |
//+------------------------------------------------------------------+
bool RetryWithBackoff(IRetryableOp *op, const int retryAttempts, const int initialDelayMs, const int delayCapMs)
{
if(CheckPointer(op) == POINTER_INVALID)
return false;
int delayMs = initialDelayMs;
bool ok = false;
for(int attempt = 0; attempt < retryAttempts && !ok; attempt++)
{
if(attempt > 0)
{
Sleep(delayMs);
delayMs = (int)MathMin(delayMs * 2, delayCapMs);
}
ok = op.TryOnce(attempt < retryAttempts - 1);
}
return ok;
}
#endif // WARRIOR_RETRY_WITH_BACKOFF_MQH
//+------------------------------------------------------------------+