(self: TxSemaphore): <A, E, R>(
effect: Effect.Effect<A, E, R>
) => Effect.Effect<A, E, R>
<A, E, R>(
self: TxSemaphore,
effect: Effect.Effect<A, E, R>
): Effect.Effect<A, E, R>Executes an effect with a single permit from the semaphore. The permit is automatically acquired before execution and released afterwards, even if the effect fails or is interrupted.
When to use
Use to run an effect while automatically acquiring and releasing one transactional permit.
Details
The permit acquisition and release operations use atomic semantics to ensure proper resource management with Effect's scoped operations.
Example (Running an effect with a permit)
import { Console, Effect, TxSemaphore } from "effect"
const program = Effect.gen(function*() {
const semaphore = yield* TxSemaphore.make(2)
// Execute database operation with automatic permit management
const result = yield* TxSemaphore.withPermit(
semaphore,
Effect.gen(function*() {
yield* Console.log("Permit acquired, accessing database...")
yield* Effect.sleep("100 millis") // Simulate database work
yield* Console.log("Database operation complete")
return "query result"
})
)
yield* Console.log(`Result: ${result}`)
// Permit is automatically released here
})export const const withPermit: {
(self: TxSemaphore): <A, E, R>(
effect: Effect.Effect<A, E, R>
) => Effect.Effect<A, E, R>
<A, E, R>(
self: TxSemaphore,
effect: Effect.Effect<A, E, R>
): Effect.Effect<A, E, R>
}
Executes an effect with a single permit from the semaphore. The permit is
automatically acquired before execution and released afterwards, even if the
effect fails or is interrupted.
When to use
Use to run an effect while automatically acquiring and releasing one
transactional permit.
Details
The permit acquisition and release operations use atomic semantics to ensure
proper resource management with Effect's scoped operations.
Example (Running an effect with a permit)
import { Console, Effect, TxSemaphore } from "effect"
const program = Effect.gen(function*() {
const semaphore = yield* TxSemaphore.make(2)
// Execute database operation with automatic permit management
const result = yield* TxSemaphore.withPermit(
semaphore,
Effect.gen(function*() {
yield* Console.log("Permit acquired, accessing database...")
yield* Effect.sleep("100 millis") // Simulate database work
yield* Console.log("Database operation complete")
return "query result"
})
)
yield* Console.log(`Result: ${result}`)
// Permit is automatically released here
})
withPermit: {
(self: TxSemaphore(parameter) self: {
permitsRef: TxRef.TxRef<number>;
capacity: number;
toString: () => string;
toJSON: () => unknown;
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; <…;
}
self: TxSemaphore): <function (type parameter) A in <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>A, function (type parameter) E in <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>E, function (type parameter) R in <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>R>(effect: Effect.Effect<A, E, R>(parameter) effect: {
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;
}
effect: import EffectEffect.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<function (type parameter) A in <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>A, function (type parameter) E in <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>E, function (type parameter) R in <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>R>) => import EffectEffect.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<function (type parameter) A in <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>A, function (type parameter) E in <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>E, function (type parameter) R in <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>R>
<function (type parameter) A in <A, E, R>(self: TxSemaphore, effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>A, function (type parameter) E in <A, E, R>(self: TxSemaphore, effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>E, function (type parameter) R in <A, E, R>(self: TxSemaphore, effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>R>(self: TxSemaphore(parameter) self: {
permitsRef: TxRef.TxRef<number>;
capacity: number;
toString: () => string;
toJSON: () => unknown;
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; <…;
}
self: TxSemaphore, effect: Effect.Effect<A, E, R>(parameter) effect: {
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;
}
effect: import EffectEffect.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<function (type parameter) A in <A, E, R>(self: TxSemaphore, effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>A, function (type parameter) E in <A, E, R>(self: TxSemaphore, effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>E, function (type parameter) R in <A, E, R>(self: TxSemaphore, effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>R>): import EffectEffect.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<function (type parameter) A in <A, E, R>(self: TxSemaphore, effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>A, function (type parameter) E in <A, E, R>(self: TxSemaphore, effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>E, function (type parameter) R in <A, E, R>(self: TxSemaphore, effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>R>
} = ((...args: any[]args: interface Array<T>Array<any>) => {
if (args: any[]args.Array<any>.length: numberGets or sets the length of the array. This is a number one higher than the highest index in the array.
length === 1) {
const [const self: anyself] = args: any[]args
return (effect: Effect.Effect<any, any, any>(parameter) effect: {
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;
}
effect: import EffectEffect.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<any, any, any>) =>
import EffectEffect.const acquireUseRelease: <
Resource,
E,
R,
A,
E2,
R2,
E3,
R3
>(
acquire: Effect<Resource, E, R>,
use: (a: Resource) => Effect<A, E2, R2>,
release: (
a: Resource,
exit: Exit.Exit<A, E2>
) => Effect<void, E3, R3>
) => Effect<A, E | E2 | E3, R | R2 | R3>
Runs resource acquisition, usage, and release as one bracketed effect.
When to use
Use to bracket acquire, use, and release logic in one effect.
Details
acquireUseRelease does the following:
- Ensures that the
Effect value that acquires the resource will not be
interrupted. Note that acquisition may still fail due to internal
reasons (such as an uncaught exception).
- Ensures that the
release Effect value will not be interrupted,
and will be executed as long as the acquisition Effect value
successfully acquires the resource.
During the time period between the acquisition and release of the resource,
the use Effect value will be executed.
If the release Effect value fails, then the entire Effect value will
fail, even if the use Effect value succeeds. If this fail-fast behavior
is not desired, errors produced by the release Effect value can be caught
and ignored.
Example (Acquiring resources with cleanup)
import { Console, Effect, Exit } from "effect"
interface Database {
readonly connection: string
readonly query: (sql: string) => Effect.Effect<string>
}
const program = Effect.acquireUseRelease(
// Acquire - connect to database
Effect.gen(function*() {
yield* Console.log("Connecting to database...")
return {
connection: "db://localhost:5432",
query: (sql: string) => Effect.succeed(`Result for: ${sql}`)
}
}),
// Use - perform database operations
(db) =>
Effect.gen(function*() {
yield* Console.log(`Connected to ${db.connection}`)
const result = yield* db.query("SELECT * FROM users")
yield* Console.log(`Query result: ${result}`)
return result
}),
// Release - close database connection
(db, exit) =>
Effect.gen(function*() {
if (Exit.isSuccess(exit)) {
yield* Console.log(`Closing connection to ${db.connection} (success)`)
} else {
yield* Console.log(`Closing connection to ${db.connection} (failure)`)
}
})
)
Effect.runPromise(program)
// Output:
// Connecting to database...
// Connected to db://localhost:5432
// Query result: Result for: SELECT * FROM users
// Closing connection to db://localhost:5432 (success)
acquireUseRelease(
const acquire: (
self: TxSemaphore
) => Effect.Effect<void>
Acquires a single permit from the semaphore. If no permits are available,
the effect will block until one becomes available.
When to use
Use to manually acquire one permit transactionally, waiting until one is
available.
Example (Acquiring a permit)
import { Console, Effect, TxSemaphore } from "effect"
const program = Effect.gen(function*() {
const semaphore = yield* TxSemaphore.make(2)
yield* Console.log("Acquiring first permit...")
yield* TxSemaphore.acquire(semaphore)
yield* Console.log("First permit acquired")
yield* Console.log("Acquiring second permit...")
yield* TxSemaphore.acquire(semaphore)
yield* Console.log("Second permit acquired")
const available = yield* TxSemaphore.available(semaphore)
yield* Console.log(`Available permits: ${available}`) // 0
})
acquire(const self: anyself),
() => effect: Effect.Effect<any, any, any>(parameter) effect: {
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;
}
effect,
() => const release: (
self: TxSemaphore
) => Effect.Effect<void>
Releases one permit back to the semaphore, making it available for
acquisition.
When to use
Use to manually return one permit after a transactional acquire.
Details
If the semaphore is already at capacity, this operation leaves the permit
count unchanged.
Example (Releasing a permit)
import { Console, Effect, TxSemaphore } from "effect"
const program = Effect.gen(function*() {
const semaphore = yield* TxSemaphore.make(2)
// Acquire a permit
yield* TxSemaphore.acquire(semaphore)
let available = yield* TxSemaphore.available(semaphore)
yield* Console.log(`After acquire: ${available}`) // 1
// Release the permit
yield* TxSemaphore.release(semaphore)
available = yield* TxSemaphore.available(semaphore)
yield* Console.log(`After release: ${available}`) // 2
})
release(const self: anyself)
)
}
const [const self: anyself, const effect: anyeffect] = args: any[]args
return import EffectEffect.const acquireUseRelease: <
Resource,
E,
R,
A,
E2,
R2,
E3,
R3
>(
acquire: Effect<Resource, E, R>,
use: (a: Resource) => Effect<A, E2, R2>,
release: (
a: Resource,
exit: Exit.Exit<A, E2>
) => Effect<void, E3, R3>
) => Effect<A, E | E2 | E3, R | R2 | R3>
Runs resource acquisition, usage, and release as one bracketed effect.
When to use
Use to bracket acquire, use, and release logic in one effect.
Details
acquireUseRelease does the following:
- Ensures that the
Effect value that acquires the resource will not be
interrupted. Note that acquisition may still fail due to internal
reasons (such as an uncaught exception).
- Ensures that the
release Effect value will not be interrupted,
and will be executed as long as the acquisition Effect value
successfully acquires the resource.
During the time period between the acquisition and release of the resource,
the use Effect value will be executed.
If the release Effect value fails, then the entire Effect value will
fail, even if the use Effect value succeeds. If this fail-fast behavior
is not desired, errors produced by the release Effect value can be caught
and ignored.
Example (Acquiring resources with cleanup)
import { Console, Effect, Exit } from "effect"
interface Database {
readonly connection: string
readonly query: (sql: string) => Effect.Effect<string>
}
const program = Effect.acquireUseRelease(
// Acquire - connect to database
Effect.gen(function*() {
yield* Console.log("Connecting to database...")
return {
connection: "db://localhost:5432",
query: (sql: string) => Effect.succeed(`Result for: ${sql}`)
}
}),
// Use - perform database operations
(db) =>
Effect.gen(function*() {
yield* Console.log(`Connected to ${db.connection}`)
const result = yield* db.query("SELECT * FROM users")
yield* Console.log(`Query result: ${result}`)
return result
}),
// Release - close database connection
(db, exit) =>
Effect.gen(function*() {
if (Exit.isSuccess(exit)) {
yield* Console.log(`Closing connection to ${db.connection} (success)`)
} else {
yield* Console.log(`Closing connection to ${db.connection} (failure)`)
}
})
)
Effect.runPromise(program)
// Output:
// Connecting to database...
// Connected to db://localhost:5432
// Query result: Result for: SELECT * FROM users
// Closing connection to db://localhost:5432 (success)
acquireUseRelease(
const acquire: (
self: TxSemaphore
) => Effect.Effect<void>
Acquires a single permit from the semaphore. If no permits are available,
the effect will block until one becomes available.
When to use
Use to manually acquire one permit transactionally, waiting until one is
available.
Example (Acquiring a permit)
import { Console, Effect, TxSemaphore } from "effect"
const program = Effect.gen(function*() {
const semaphore = yield* TxSemaphore.make(2)
yield* Console.log("Acquiring first permit...")
yield* TxSemaphore.acquire(semaphore)
yield* Console.log("First permit acquired")
yield* Console.log("Acquiring second permit...")
yield* TxSemaphore.acquire(semaphore)
yield* Console.log("Second permit acquired")
const available = yield* TxSemaphore.available(semaphore)
yield* Console.log(`Available permits: ${available}`) // 0
})
acquire(const self: anyself),
() => const effect: anyeffect,
() => const release: (
self: TxSemaphore
) => Effect.Effect<void>
Releases one permit back to the semaphore, making it available for
acquisition.
When to use
Use to manually return one permit after a transactional acquire.
Details
If the semaphore is already at capacity, this operation leaves the permit
count unchanged.
Example (Releasing a permit)
import { Console, Effect, TxSemaphore } from "effect"
const program = Effect.gen(function*() {
const semaphore = yield* TxSemaphore.make(2)
// Acquire a permit
yield* TxSemaphore.acquire(semaphore)
let available = yield* TxSemaphore.available(semaphore)
yield* Console.log(`After acquire: ${available}`) // 1
// Release the permit
yield* TxSemaphore.release(semaphore)
available = yield* TxSemaphore.available(semaphore)
yield* Console.log(`After release: ${available}`) // 2
})
release(const self: anyself)
)
}) as any