SECTION IV: Concurrency and Asynchrony

AVAP implements a thread-based concurrency model that enables fire-and-forget execution or parallel execution with later synchronization. This is essential for tasks such as email dispatching, log processing, or querying multiple external APIs simultaneously.

4.1 Launching Background Processes (go_async)

The go_async command extracts a block of code from the main sequential flow and places it into a parallel execution queue.

Interface
go_async(thread_id)
Execution Mechanics

Identification:
The programmer assigns a thread_id (a string or variable) to reference the process later.

Forking:
When invoked, the AVAP engine creates a new native thread. The main flow immediately continues to the next instruction after the go_async block.

Context Isolation:
The asynchronous thread inherits a snapshot copy of the variable state at the moment of invocation, allowing it to operate safely without interfering with the main thread.

Example: Immediate Response with Long-Running Process
addParam("email", destination)

go_async("email_dispatch")
    // This block takes 5 seconds, but the API does not wait
    mail_service.send(destination, "Welcome to AVAP")
end()

addVar(msg, "Your email is being processed in the background")
addResult(msg)
// The client receives the response in milliseconds
4.2 Result Synchronization (gather)

When the main flow requires data generated by an asynchronous thread to proceed, the gather synchronization mechanism is used.

Interface
gather(thread_id, timeout)
Specifications

thread_id:
The identifier used in the go_async command.

timeout (Seconds):
Maximum time the main thread will wait. If the asynchronous thread does not finish within this period, AVAP raises an exception that can be caught (see Section III).

Technical Behavior

Controlled Blocking:
The main thread is suspended until the specified thread_id completes.

State Recovery:
Once synchronized, any variables modified within the asynchronous thread are merged back into the main thread’s context.

4.3 Optimized Parallel Execution (Fan-Out Pattern)

AVAP allows launching multiple threads and then waiting for all of them, reducing total execution time to the duration of the slowest thread instead of the sum of all execution times.

Example: Querying Multiple Databases
go_async("db_north")
    data_north = north_connector.query("SELECT...")
end()

go_async("db_south")
    data_south = south_connector.query("SELECT...")
end()

// Wait for both (Maximum 10 seconds)
gather("db_north", 10)
gather("db_south", 10)

// Combine results using Section I mechanisms
total_result = data_north + data_south
addResult(total_result)
4.4 Promise State in Output

As mentioned in Section II, if a variable that is still being processed in an asynchronous thread is passed to addResult, AVAP manages the response intelligently:

If the thread is still running:
The output JSON will display "variable": "promised" or the thread ID.

If the thread failed:
The error is logged internally and the variable is set to None.

If gather was used before addResult:
The fully processed real value is returned in the response.

Examples

1. Background Process Fire-and-Forget

Code snippet

go_async("notification_thread")
    // This block runs on its own
    RequestPost("https://hooks.slack.com/...", {}, body, r)
end()

2. Synchronization (Gather)

Code snippet

go_async("heavy_calc")
    result = (500 * 250) / 3
end()
gather("heavy_calc", 10) // Waits until it finishes
addResult(result)

3. Connector Parallelism

Code snippet

go_async("db_1")
    res1 = db1.query("SELECT...")
end()
go_async("db_2")
    res2 = db2.query("SELECT...")
end()

4. Gather with Safety Timeout

Code snippet

gather("external_process", 5)
// If it doesn't finish in 5s, the script continues or fails depending on config

5. Using "Promised" State

Code snippet

go_async("long_task")
    final = "Finished"
end()
addResult(final) // You will see "promised" in the JSON

6. Validation After Gather

Code snippet

gather("data_thread", 2)
if(thread_data, None, "!=")
    addResult(thread_data)
end()

7. Multi-Threading for Auditing

Code snippet

go_async("audit_thread")
    ormDirect("INSERT INTO audit...", r)
end()

8. Dynamic Gather in a Loop

Code snippet

startLoop(h, 1, 3)
    gather("thread_${h}", 1)
endLoop()

9. Asynchronous Tax Calculation

Code snippet

go_async("tax_engine")
    total_tax = total * 0.21
end()

10. Try-Except Inside an Async Thread

Code snippet

go_async("safe_thread")
    try
        // Task that may fail
    exception(err)
        // Log the error locally
    end()
end()