Timeouts in Nim

Timeouts are important for programs that connect to external resources or that otherwise need to bound execution time. Implementing timeouts in Nim is straightforward using channels and the select statement.

import std/[asyncdispatch, asyncfutures, strformat]

proc main() {.async.} =
  # For our example, suppose we're executing an external
  # call that returns its result on a channel `c1`
  # after 2s. Note that we're using an AsyncChannel,
  # which is similar to a buffered channel in other languages.
  let c1 = newAsyncChannel[string](1)
  asyncCheck (proc() {.async.} =
    await sleepAsync(2000)
    await c1.send("result 1")
  )()

  # Here's the `select` implementing a timeout.
  # We use `race` to await multiple futures concurrently.
  # The first completed future will be the result.
  let res = await race(
    c1.recv(),
    sleepAsync(1000)
  )

  if res.index == 0:
    echo res.read(string)
  else:
    echo "timeout 1"

  # If we allow a longer timeout of 3s, then the receive
  # from `c2` will succeed and we'll print the result.
  let c2 = newAsyncChannel[string](1)
  asyncCheck (proc() {.async.} =
    await sleepAsync(2000)
    await c2.send("result 2")
  )()

  let res2 = await race(
    c2.recv(),
    sleepAsync(3000)
  )

  if res2.index == 0:
    echo res2.read(string)
  else:
    echo "timeout 2"

waitFor main()

Running this program shows the first operation timing out and the second succeeding.

$ nim c -r timeouts.nim
timeout 1
result 2

In this Nim version, we use the asyncdispatch module to handle asynchronous operations. The AsyncChannel is used instead of Go’s buffered channels, and the race procedure simulates the select statement’s behavior. The asyncCheck procedure is used to run asynchronous procedures concurrently, similar to goroutines in Go.

The overall structure and logic remain the same, with timeouts implemented using sleepAsync and race. This demonstrates how Nim can handle concurrent operations and timeouts in a manner similar to Go, albeit with slightly different syntax and concepts.