async_postgres/async_backend

Search:
Group by:

Async backend configuration module.

Provides unified async framework abstraction for both asyncdispatch and chronos. Select the backend at compile time with -d:asyncBackend=asyncdispatch|chronos. Default backend is asyncdispatch.

Types

AsyncTimeoutError = object of CatchableError
Raised when an async operation times out (chronos-compatible name).
CancelledError = object of CatchableError
Raised when an async operation is cancelled.
Duration = distinct int64
Time interval in nanoseconds. API-compatible with chronos.Duration.
Moment = object
Monotonic timestamp. API-compatible with chronos.Moment.

Consts

hasAsyncDispatch = true
true when the asyncdispatch backend is selected.
hasChronos = false
true when the chronos backend is selected.
hasTls = false
true when the selected backend can perform TLS. Gates every symbol whose definition depends on backend TLS APIs; keeping this in one place prevents drift between call sites and their when guards.
ZeroDuration = 0'i64
A zero-length duration.

Procs

proc `$`(d: Duration): string {....raises: [], tags: [], forbids: [].}
proc `+`(a, b: Duration): Duration {.borrow, ...raises: [], tags: [], forbids: [].}
proc `+`(a: Moment; b: Duration): Moment {....raises: [], tags: [], forbids: [].}
proc `-`(a, b: Duration): Duration {.borrow, ...raises: [], tags: [], forbids: [].}
proc `-`(a, b: Moment): Duration {....raises: [], tags: [], forbids: [].}
proc `-`(a: Moment; b: Duration): Moment {....raises: [], tags: [], forbids: [].}
proc `<`(a, b: Duration): bool {.borrow, ...raises: [], tags: [], forbids: [].}
proc `<`(a, b: Moment): bool {....raises: [], tags: [], forbids: [].}
proc `<=`(a, b: Duration): bool {.borrow, ...raises: [], tags: [], forbids: [].}
proc `<=`(a, b: Moment): bool {....raises: [], tags: [], forbids: [].}
proc `==`(a, b: Duration): bool {.borrow, ...raises: [], tags: [], forbids: [].}
proc allFutures[T](futures: seq[Future[T]]): Future[void]
Wait for all futures to complete (success or failure).
proc asyncSpawn(fut: Future[void]) {....raises: [Exception], tags: [RootEffect],
                                     forbids: [].}
Fire-and-forget a future. If the future fails with an unhandled exception, a Defect is raised (matching chronos behaviour). The caller is responsible for error handling inside the async proc.
proc cancelAndWait(fut: Future[void]): Future[void] {....stackTrace: false,
    raises: [Exception], tags: [RootEffect], forbids: [].}
Cancel a future and wait for completion.
Warning: On asyncdispatch this is a no-op — the future is neither cancelled nor awaited. asyncdispatch has no cancellation primitive. Callers must not assume the future has stopped: any buffer it holds via addr remains live, and any socket write it scheduled will still complete. Do not reuse the affected resource (socket, buffer) after calling this under asyncdispatch. chronos cancels the future properly.
proc cancelTimer(fut: Future[void]) {....raises: [], tags: [], forbids: [].}
No-op under asyncdispatch: timers cannot be cancelled, but they complete harmlessly and are garbage-collected. Provided for API parity with chronos, which does cancel the timer via cancelSoon.
proc completed[T](fut: Future[T]): bool
Check if a future completed successfully (not failed). Chronos-compatible name for finished and not failed.
proc hours(h: int): Duration {....raises: [], tags: [], forbids: [].}
Create a Duration from hours.
proc milliseconds(ms: int): Duration {....raises: [], tags: [], forbids: [].}
Create a Duration from milliseconds.
proc minutes(m: int): Duration {....raises: [], tags: [], forbids: [].}
Create a Duration from minutes.
proc nanoseconds(ns: int): Duration {....raises: [], tags: [], forbids: [].}
Create a Duration from nanoseconds.
proc nanoseconds(ns: int64): Duration {....raises: [], tags: [], forbids: [].}
Create a Duration from nanoseconds.
proc now(T: typedesc[Moment]): Moment
Get the current monotonic timestamp.
proc registerFdReader(fd: cint; cb: proc () {....gcsafe, raises: [].}) {.
    ...raises: [OSError, CatchableError], tags: [], forbids: [].}
Register a file descriptor for read-readiness notifications on the event loop. cb is called whenever the fd becomes readable.
proc remainingDeadlineDuration(deadline: Moment): Duration {....raises: [],
    tags: [TimeEffect], forbids: [].}

Compute the remaining Duration until deadline. When the deadline has passed, returns 1 millisecond so the next wait() / simpleExec(timeout) fires reliably. A nanoseconds(1) floor would be ignored by chronos's wait when the awaited future completes synchronously (e.g. socket recv with bytes already buffered), letting the loop run indefinitely; 1ms is above chronos's timer resolution so the timer fires deterministically. Returning ZeroDuration would mean "no timeout" in this codebase — the opposite of what a missed deadline should do.

Practical minimum: because of the 1ms floor and per-call event-loop scheduling overhead, deadlines smaller than a few milliseconds are not meaningfully enforced — the floor will kick in on the first call and subsequent ms-level waits still need an event-loop tick to fire. Useful deadlines for the *Deadline helpers start in the tens of milliseconds.

proc scheduleSoon(cb: proc () {....gcsafe, raises: [].}) {....raises: [], tags: [],
    forbids: [].}
Schedule cb to run on the next event loop tick.
proc seconds(s: int): Duration {....raises: [], tags: [], forbids: [].}
Create a Duration from seconds.
proc sleepAsync(d: Duration): Future[void] {....raises: [], tags: [TimeEffect],
    forbids: [].}
Sleep for the given Duration.
proc sleepMsAsync(ms: int): Future[void] {....raises: [], tags: [TimeEffect],
    forbids: [].}
Sleep for ms milliseconds.
proc toMilliseconds(d: Duration): int {....raises: [], tags: [], forbids: [].}
Convert Duration to milliseconds (for asyncdispatch APIs).
proc unregisterFdReader(fd: cint) {....raises: [], tags: [], forbids: [].}
Remove a previously registered read-readiness watcher from the event loop.
proc wait[T](fut: Future[T]; timeout: Duration;
             onOrphan: proc (fut: Future[T]) {....gcsafe.} = nil): Future[T] {.
    ...stackTrace: false.}

Wait for a future with a timeout. Raises AsyncTimeoutError on timeout. API-compatible with chronos Future.wait().

onOrphan cleanup hook asyncdispatch has no cancellation. When a timeout fires, the inner future keeps running in the background until its I/O completes. This onOrphan callback is registered on the inner future and called once that orphan eventually completes. Use it to close a live connection or release other resources the orphan holds. When onOrphan is omitted the default handler drains the orphan's outcome (clears a late failure) but does not release other resources. Pass an explicit onOrphan when the orphan owns a connection or other live resource.

Under chronos the onOrphan argument is accepted but never called — futures are properly cancelled on timeout and no orphan remains.

Macros

macro declareAsyncCallback(name: untyped; procType: untyped;
                           doc: static string = ""): untyped

Declare name* as an async callback proc-type, injecting backend-appropriate pragmas so callers do not repeat when hasChronos: ... else: ... blocks.

chronos gets {.async: (raises: [CatchableError]), gcsafe.}; asyncdispatch gets {.gcsafe.}. procType must be a bare proc-type expression with no pragmas attached. Optional doc becomes the emitted type's docstring.

Templates

template makeAsyncSeqByteCallback(cbType: typedesc; body: untyped): untyped
Build a cbType producer callback returning Future[seq[byte]]. {.async.} handles both the final-expression form and early return <expr> inside body symmetrically across backends.
template makeAsyncSinkByteCallback(cbType: typedesc; body: untyped): untyped
Build a cbType async callback receiving data: sink seq[byte] and returning Future[void]. Split from a generic void-shape maker because splicing the parameter type through an untyped template param confuses asyncdispatch's {.async.} macro; keeping the whole parameter literal sidesteps that. data is injected into body's scope.