assistance-engine/ingestion/docs/20_Concurrency_asynchrony.txt

179 lines
4.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 threads 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()