Effect<never, never, Transaction>Retries the current transaction by signaling that it must be retried.
Details
NOTE: the transaction retries on any change to transactional values (i.e. TxRef) accessed in its body.
Example (Retrying transactions)
import { Effect, TxRef } from "effect"
const program = Effect.gen(function*() {
// create a transactional reference
const ref = yield* TxRef.make(0)
// forks a fiber that increases the value of `ref` every 100 millis
yield* Effect.forkChild(Effect.forever(
// update to transactional value
Effect.tx(TxRef.update(ref, (n) => n + 1)).pipe(Effect.delay("100 millis"))
))
// the following will retry 10 times until the `ref` value is 10
yield* Effect.tx(Effect.gen(function*() {
const value = yield* TxRef.get(ref)
if (value < 10) {
yield* Effect.log(`retry due to value: ${value}`)
return yield* Effect.txRetry
}
yield* Effect.log(`transaction done with value: ${value}`)
}))
})
Effect.runPromise(program).catch(console.error)export const const txRetry: Effect<
never,
never,
Transaction
>
const txRetry: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
Retries the current transaction by signaling that it must be retried.
Details
NOTE: the transaction retries on any change to transactional values (i.e. TxRef) accessed in its body.
Example (Retrying transactions)
import { Effect, TxRef } from "effect"
const program = Effect.gen(function*() {
// create a transactional reference
const ref = yield* TxRef.make(0)
// forks a fiber that increases the value of `ref` every 100 millis
yield* Effect.forkChild(Effect.forever(
// update to transactional value
Effect.tx(TxRef.update(ref, (n) => n + 1)).pipe(Effect.delay("100 millis"))
))
// the following will retry 10 times until the `ref` value is 10
yield* Effect.tx(Effect.gen(function*() {
const value = yield* TxRef.get(ref)
if (value < 10) {
yield* Effect.log(`retry due to value: ${value}`)
return yield* Effect.txRetry
}
yield* Effect.log(`transaction done with value: ${value}`)
}))
})
Effect.runPromise(program).catch(console.error)
txRetry: interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<never, never, class Transactionclass Transaction {
key: Identifier;
Service: {
retry: boolean;
journal: Map<TxRef<any>, { readonly version: number; value: any }>;
};
}
Service that holds the current transaction state.
Details
It includes a journal that stores non-committed changes to TxRef values and
a retry flag that records whether the transaction should be retried.
Example (Building transactions)
import { Effect } from "effect"
// Transaction class for software transactional memory operations
const txEffect = Effect.gen(function*() {
const tx = yield* Effect.Transaction
// Use transaction for coordinated state changes
return "Transaction complete"
})
Transaction> = const flatMap: {
<A, B, E1, R1>(
f: (a: A) => Effect<B, E1, R1>
): <E, R>(
self: Effect<A, E, R>
) => Effect<B, E1 | E, R1 | R>
<A, E, R, B, E1, R1>(
self: Effect<A, E, R>,
f: (a: A) => Effect<B, E1, R1>
): Effect<B, E | E1, R | R1>
}
flatMap(
class Transactionclass Transaction {
key: Identifier;
Service: {
retry: boolean;
journal: Map<TxRef<any>, { readonly version: number; value: any }>;
};
of: (this: void, self: { retry: boolean; readonly journal: Map<TxRef<any>, { readonly version: number; value: any }> }) => { retry: boolean; readonly journal: Map<TxRef<any>, { readonly version: number; value: any }> };
context: (self: { retry: boolean; readonly journal: Map<TxRef<any>, { readonly version: number; value: any }> }) => Context.Context<Transaction>;
use: (f: (service: { retry: boolean; readonly journal: Map<TxRef<any>, { readonly version: number; value: any }> }) => Effect<A, E, R>) => Effect<A, E, Transaction | R>;
useSync: (f: (service: { retry: boolean; readonly journal: Map<TxRef<any>, { readonly version: number; value: any }> }) => A) => Effect<A, never, Transaction>;
Identifier: Identifier;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
Service that holds the current transaction state.
Details
It includes a journal that stores non-committed changes to TxRef values and
a retry flag that records whether the transaction should be retried.
Example (Building transactions)
import { Effect } from "effect"
// Transaction class for software transactional memory operations
const txEffect = Effect.gen(function*() {
const tx = yield* Effect.Transaction
// Use transaction for coordinated state changes
return "Transaction complete"
})
Transaction,
(state: {
retry: boolean
readonly journal: Map<
TxRef<any>,
{ readonly version: number; value: any }
>
}
(parameter) state: {
retry: boolean;
journal: Map<TxRef<any>, { readonly version: number; value: any }>;
}
state) => {
state: {
retry: boolean
readonly journal: Map<
TxRef<any>,
{ readonly version: number; value: any }
>
}
(parameter) state: {
retry: boolean;
journal: Map<TxRef<any>, { readonly version: number; value: any }>;
}
state.retry = true
return const interrupt: Effect<never>const interrupt: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
Returns an effect that is immediately interrupted.
Example (Creating an interrupted effect)
import { Effect } from "effect"
const program = Effect.gen(function*() {
return yield* Effect.interrupt
yield* Effect.succeed("This won't execute and is unreachable")
})
Effect.runPromise(program).catch(console.error)
// Throws: InterruptedException
interrupt
}
)