(self: TxSemaphore): Effect.Effect<void, never, Scope.Scope>Acquires a single permit from the semaphore in a scoped manner. The permit will be automatically released when the scope is closed, even if effects within the scope fail or are interrupted.
When to use
Use to acquire one transactional permit for the lifetime of the current scope.
Details
The permit acquisition and release operations use atomic semantics to ensure proper resource management with Effect's scoped operations.
Example (Acquiring a scoped permit)
import { Console, Effect, TxSemaphore } from "effect"
const program = Effect.gen(function*() {
const semaphore = yield* TxSemaphore.make(3)
yield* Effect.scoped(
Effect.gen(function*() {
// Acquire permit for the duration of this scope
yield* TxSemaphore.withPermitScoped(semaphore)
yield* Console.log("Permit acquired for scope")
// Do work within the scope
yield* Effect.sleep("500 millis")
yield* Console.log("Work completed")
// Permit will be automatically released when scope closes
})
)
yield* Console.log("Scope closed, permit released")
})export const const withPermitScoped: (
self: TxSemaphore
) => Effect.Effect<void, never, Scope.Scope>
Acquires a single permit from the semaphore in a scoped manner. The permit
will be automatically released when the scope is closed, even if effects
within the scope fail or are interrupted.
When to use
Use to acquire one transactional permit for the lifetime of the current
scope.
Details
The permit acquisition and release operations use atomic semantics to ensure
proper resource management with Effect's scoped operations.
Example (Acquiring a scoped permit)
import { Console, Effect, TxSemaphore } from "effect"
const program = Effect.gen(function*() {
const semaphore = yield* TxSemaphore.make(3)
yield* Effect.scoped(
Effect.gen(function*() {
// Acquire permit for the duration of this scope
yield* TxSemaphore.withPermitScoped(semaphore)
yield* Console.log("Permit acquired for scope")
// Do work within the scope
yield* Effect.sleep("500 millis")
yield* Console.log("Work completed")
// Permit will be automatically released when scope closes
})
)
yield* Console.log("Scope closed, permit released")
})
withPermitScoped = (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): 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<void, never, import ScopeScope.Scope> =>
import EffectEffect.const acquireRelease: <A, E, R, R2>(
acquire: Effect<A, E, R>,
release: (
a: A,
exit: Exit.Exit<unknown, unknown>
) => Effect<unknown, never, R2>,
options?: { readonly interruptible?: boolean }
) => Effect<A, E, R | R2 | Scope>
Constructs a scoped resource from an acquisition effect and a release
finalizer.
When to use
Use to acquire a scoped resource with an explicit release finalizer.
Details
If acquisition succeeds, the release finalizer is added to the current scope
and is guaranteed to run when that scope closes. The finalizer receives the
Exit value used to close the scope.
By default, acquisition is protected by an uninterruptible region. Pass
{ interruptible: true } to allow the acquisition effect to be interrupted.
Example (Acquiring and releasing a resource)
import { Console, Effect, Exit } from "effect"
// Simulate a resource that needs cleanup
interface FileHandle {
readonly path: string
readonly content: string
}
// Acquire a file handle
const acquire = Effect.gen(function*() {
yield* Console.log("Opening file")
return { path: "/tmp/file.txt", content: "file content" }
})
// Release the file handle
const release = (handle: FileHandle, exit: Exit.Exit<unknown, unknown>) =>
Console.log(
`Closing file ${handle.path} with exit: ${
Exit.isSuccess(exit) ? "success" : "failure"
}`
)
// Create a scoped resource
const resource = Effect.acquireRelease(acquire, release)
// Use the resource within a scope
const program = Effect.scoped(
Effect.gen(function*() {
const handle = yield* resource
yield* Console.log(`Using file: ${handle.path}`)
return handle.content
})
)
acquireRelease(
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(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),
() => 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(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)
)