export const tryUntil = <A, B extends A>({
try: doTry,
until: isDone,
sleepDuration = Duration.millis(200),
maxDuration,
}: {
try: () => A;
until: Predicate.Refinement<A, B>;
sleepDuration?: Duration.Duration;
maxDuration: Duration.Duration;
}): Effect.Effect<B, Error, never> => {
const immediateValue = doTry();
if (isDone(immediateValue)) {
return Effect.succeed(immediateValue);
}
// Continually call it again on a schedule with a delay
return Effect.sync(doTry).pipe(
// Sleep in between each attempt
Effect.delay(sleepDuration),
// Keep doing this until the predicate passes
Effect.repeat({ until: isDone }),
// Until a timeout occurs
Effect.timeoutFail({
onTimeout: () =>
new Error(
`Timed out after ${Duration.format(maxDuration)} waiting for value to pass predicate`,
),
duration: maxDuration,
}),
);
};
export const tryUntil = <A, B extends A>({
try: doTry,
until: isDone,
sleepDuration = Duration.millis(200),
maxDuration,
}: {
try: () => A;
until: Predicate.Refinement<A, B>;
sleepDuration?: Duration.Duration;
maxDuration: Duration.Duration;
}): Effect.Effect<B, Error, never> => {
const immediateValue = doTry();
if (isDone(immediateValue)) {
return Effect.succeed(immediateValue);
}
// Continually call it again on a schedule with a delay
return Effect.sync(doTry).pipe(
// Sleep in between each attempt
Effect.delay(sleepDuration),
// Keep doing this until the predicate passes
Effect.repeat({ until: isDone }),
// Until a timeout occurs
Effect.timeoutFail({
onTimeout: () =>
new Error(
`Timed out after ${Duration.format(maxDuration)} waiting for value to pass predicate`,
),
duration: maxDuration,
}),
);
};