forked from MrBaro75/Warrior_EA
49 lines
2.4 KiB
MQL5
49 lines
2.4 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| 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
| |||
//+------------------------------------------------------------------+
|