Если честно, я не понимаю, что означает 1 галочка , в вашем случае? Это наносекунда или больше? Ваш глобальный тайм-аут должен быть больше вашего локального тайм-аута.
Но, как я вижу, у вас не указан локальный . TryEnterLock
должен получить TimeSpan, чтобы не блокировать вызывающего абонента на бесконечное время. Если вы посмотрите на встроенные примитивы syn c, большинство из них предоставляют такие возможности: Monitor.TryEnter , SpinLock.TryEnter , WaitHandle.WaitOne , et c.
Итак, подытожим:
var timeoutPolicy = Policy.Timeout(TimeSpan.FromMilliseconds(1000));
var retryPolicy = Policy.HandleResult(false)
.WaitAndRetryForever(_ => TimeSpan.FromMilliseconds(500));
var resilientStrategy = Policy.Wrap(timeoutPolicy, retryPolicy);
var result = resilientStrategy.Execute(() => this.TryEnterLock(TimeSpan.FromMilliseconds(100)));
Значения тайм-аута и задержки должны быть скорректированы в соответствии с потребностями вашего бизнеса. Я настоятельно рекомендую вам регистрировать, когда срабатывает глобальный тайм-аут (onTimeout
/ onTimeoutAsync
) и когда повторяются попытки (onRetry
/ onRetryAsync
), чтобы иметь возможность точно настроить / откалибровать эти значения.
РЕДАКТИРОВАТЬ: на основе комментариев к этому сообщению
Как оказалось, нет контроля над timeoutFromApiCaller
, поэтому он может быть произвольно маленьким. (В данном примере это всего несколько наносекунд, с целью подчеркнуть проблему.) Итак, чтобы иметь хотя бы один гарантированный вызов, мы должны использовать Резервную политику .
Вместо того, чтобы вручную вызывать TryEnterLock
вне политик, мы должны называть его последним действием для удовлетворения требований. Поскольку политики используют эскалацию, поэтому всякий раз, когда внутренний выходит из строя, он делегирует проблему следующей внешней политике.
Итак, если предоставленный тайм-аут настолько мал, что Действие не может быть завершено sh до этого периода, тогда оно выдаст TimeoutRejectedException
. С помощью Fallback мы можем справиться с этим, и действие может быть выполнено снова , но теперь без ограничения времени ожидания. Это даст нам желаемую хотя бы одну гарантию.
var atLeastOnce = Policy.Handle<TimeoutRejectedException>
.Fallback((ct) => this.TryEnterLock());
var globalTimeout = Policy.Timeout(TimeSpan.FromMilliseconds(1000));
var foreverRetry = Policy.HandleResult(false)
.WaitAndRetryForever(_ => TimeSpan.FromMilliseconds(500));
var resilientStrategy = Policy.Wrap(atLeastOnce, globalTimeout, foreverRetry);
var result = resilientStrategy.Execute(() => this.TryEnterLock());