import { Cause, Data, Effect, Fiber, Schedule } from 'effect';
import { setTimeout } from 'node:timers/promises';
class RequestError extends Data.TaggedError('RequestError') {}
let counter = 0;
const task = Effect.gen(function* () {
const request = Effect.tryPromise({
catch: () => new RequestError(),
try: async () => {
console.log('running request');
await setTimeout(100);
counter++;
if (counter > 12) {
console.log('request done');
return 'ok' as const;
}
throw new Error('Connection setup failed');
},
}).pipe(
Effect.retry({
until: (err) => err._tag !== 'RequestError',
schedule: Schedule.spaced('1 seconds'),
}),
Effect.timeoutTo({
duration: '10 seconds',
onSuccess: (v) => v,
onTimeout: () => 'timeout' as const,
})
);
const fiber = yield* request.pipe(Effect.forkDaemon);
return {
interrupt: () => {
Effect.runSync(Fiber.interruptFork(fiber));
},
promise: Effect.runPromise(
Effect.merge(
fiber.pipe(
Effect.catchAllCause((cause) => {
if (Cause.isInterrupted(cause)) {
console.log('interrupted');
return Effect.fail('interrupted' as const);
}
return Effect.fail('unknown_error' as const);
})
)
)
),
};
});
const result = await Effect.runPromise(task);
console.log('result ---->', result);
await setTimeout(3000);
result.interrupt();
const promise = await result.promise;
console.log('promise ---->', promise);
import { Cause, Data, Effect, Fiber, Schedule } from 'effect';
import { setTimeout } from 'node:timers/promises';
class RequestError extends Data.TaggedError('RequestError') {}
let counter = 0;
const task = Effect.gen(function* () {
const request = Effect.tryPromise({
catch: () => new RequestError(),
try: async () => {
console.log('running request');
await setTimeout(100);
counter++;
if (counter > 12) {
console.log('request done');
return 'ok' as const;
}
throw new Error('Connection setup failed');
},
}).pipe(
Effect.retry({
until: (err) => err._tag !== 'RequestError',
schedule: Schedule.spaced('1 seconds'),
}),
Effect.timeoutTo({
duration: '10 seconds',
onSuccess: (v) => v,
onTimeout: () => 'timeout' as const,
})
);
const fiber = yield* request.pipe(Effect.forkDaemon);
return {
interrupt: () => {
Effect.runSync(Fiber.interruptFork(fiber));
},
promise: Effect.runPromise(
Effect.merge(
fiber.pipe(
Effect.catchAllCause((cause) => {
if (Cause.isInterrupted(cause)) {
console.log('interrupted');
return Effect.fail('interrupted' as const);
}
return Effect.fail('unknown_error' as const);
})
)
)
),
};
});
const result = await Effect.runPromise(task);
console.log('result ---->', result);
await setTimeout(3000);
result.interrupt();
const promise = await result.promise;
console.log('promise ---->', promise);