Retry Reconciliation

4 min read
Suggest an edit

In standard imperative programming (like Python, Go, or Node.js), when you want to send data to an external API that might be down, you use a try/catch block wrapped in a while loop, often with a sleep() function to create a delay (Exponential Backoff).

The problem? While the code is "sleeping," it is holding a thread hostage. If the server loses power during that 5-second sleep, the memory is wiped, the retry count is lost, and the task drops into the void forever.

The Code: Retry Reconciliation in Ved

Because Ved strictly prohibits try/catch exceptions and blocking functions like sleep(), you handle retries by turning them into a state machine.

Here is what the reconciliation code looks like in Ved's syntax:

domain PaymentSync {
  state {
    status: string     // e.g., "pending", "success", "failed"
    attempts: int
  }

  // The system rests ONLY when one of these two realities is true
  goal SyncedOrDeadLetter {
    predicate status == "success" || attempts >= 3
  }

  transition SyncData {
    step {
      // If we aren't successful yet, and we have retries left
      if status != "success" && attempts < 3 {
        emit API.SendPayment()
        attempts += 1
      }
    }
  }
}

How it Executes (The Control Loop)

Assume status starts as "pending" and attempts starts at 0.

  1. Tick 1: The runtime checks the goal. It is false (status is pending, attempts is 0). It triggers the SyncData transition. The code emits an Intent to send the payment and increments attempts to 1.
  2. The Effect Boundary: The actual HTTP request is made in the background by the Impure Effect Adapter. The Ved domain yields the CPU and goes to sleep.
  3. The Failure (Tick 2): The API is down! The Effect Adapter catches the HTTP 500 error and drops it into the Domain's mailbox. Ved updates the state to show the failure.
  4. The Retry (Tick 3): The runtime wakes up. It evaluates the goal again. Because status is still not "success" but attempts is only 1, the goal is still false. It triggers SyncData again.
  5. Stability: This loops until either the API returns a 200 OK (status == "success") OR attempts hits 3. At that point, the goal evaluates to true, and the program permanently rests.

Behavior

  • Task retries until completed

  • Retries are deterministic

  • System stabilizes once goal satisfied


Why This Matters

Traditional retries:

  • timing-dependent
  • can cause duplication

Ved:

  • deterministic retry logic
  • consistent behavior

Key Takeaways

1. Crash-Proof Retries (The Magic of COW Snapshots)

If a Python script is on "Attempt 2 of 3" and the server's power cable is unplugged, that data is gone. In Ved, because the memory state (attempts: 2) is flushed to disk via Copy-On-Write (COW) snapshots after every deterministic tick, a hardware crash means nothing. When the server reboots, Ved instantly loads the snapshot. The program wakes up, realizes it is on Attempt 2, and seamlessly executes Attempt 3. It survives hardware death without a database.

2. CPU Liberation (Zero-Cost Waiting)

In standard languages, a sleep(5000) command actively holds onto a chunk of system memory and a CPU thread doing absolutely nothing. If you have 10,000 network requests backing up, you will run out of threads and crash your server (Thread Starvation). In Ved, because you emit an Intent and let the runtime handle the network, the Domain completely yields the CPU. You could have 1,000,000 tasks waiting for a retry, and they would consume zero CPU cycles while they wait.

3. No More "Silent Failures"

Have you ever seen an app fail silently because a developer wrote a try/catch block but forgot to put a console.log() inside the catch? Ved makes that impossible. Because there are no exceptions, an error cannot "disappear." It is injected directly into the Domain's state. If your code doesn't mathematically resolve that state to reach a Goal, the system stays awake, the scheduler flags it, and telemetry alerts you that a domain is failing to converge.

4. The "Dead Letter" Guarantee

By writing the goal as status == "success" || attempts >= 3, you are mathematically guaranteeing that this loop will not run forever. The compiler and the runtime know that this operation has a strict boundary. In distributed systems, bounded execution is the difference between a minor blip and a massive cloud bill from an infinite loop.

Summary

Retries become:

convergence toward completion