Request for guidance: CancellableTaskEither #1440
-
I should start by saying that I know approximately zero Category Theory, and this whole thing may be fundamentally misguided. Intuitively, it seems like what I'm after could be possible given the nature of chain/flatMap/bind, but that is about where my comprehension tapers off. Ideally, I would like something like this: import { pipe } from 'fp-ts/lib/function'
import * as IO from 'fp-ts/lib/IO'
import * as TE from 'fp-ts/lib/TaskEither'
import * as CTE from './fp-ts-extensions/CancellableTaskEither'
type User = {}
declare const getUser: (id: string) => TE.TaskEither<'API_ERROR', User>
declare const saveUser: (user: User) => TE.TaskEither<'DB_ERROR', void>
interface Request {
userId: string
isCancelled: IO.IO<boolean>
}
type HandleRequestWithCancellation = (
req: Request
) => TE.TaskEither<'API_ERROR' | 'DB_ERROR' | 'REQUEST_CANCELLED', void>
/**
*
* I would like this to return Left<'REQUEST_CANCELLED'> if the bit flips while
* `getUser()` is in-flight, without attempting `saveUser()`.
*/
export const handleRequestWithCancellation: HandleRequestWithCancellation = ({
userId,
isCancelled,
}) =>
pipe(
userId,
getUser,
TE.chainW(saveUser),
CTE.asCancellable(isCancelled, () => 'REQUEST_CANCELLED')
) I'm at a bit of a loss for where to start, and wondering if this is even possible. Is there a way to do this and lift an arbitrary We have a large code-base that deals in |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
Look into fluture and the bindings called fp-ts-fluture Flutures look like they can be cancelled. |
Beta Was this translation helpful? Give feedback.
-
@andrewreineke you can check const REQUEST_CANCELLED = 'REQUEST_CANCELLED' as const
export const handleRequestWithCancellation: HandleRequestWithCancellation = ({ userId, isCancelled }) =>
pipe(
getUser(userId),
TE.chainW((user) =>
pipe(
TE.rightIO(isCancelled),
TE.chainW((b) => (b ? TE.left(REQUEST_CANCELLED) : saveUser(user)))
)
)
) or using "do notation" export const handleRequestWithCancellation2: HandleRequestWithCancellation = ({ userId, isCancelled }) =>
pipe(
TE.Do,
TE.bind('user', () => getUser(userId)),
TE.bind('isCancelled', () => TE.rightIO(isCancelled)),
TE.chainW(({ isCancelled, user }) => (isCancelled ? TE.left(REQUEST_CANCELLED) : saveUser(user)))
) |
Beta Was this translation helpful? Give feedback.
@andrewreineke you can check
isCancelled
before callingsaveUser
or using "do notation"