Experimental thought: Fast API simple tweak that unlocks hidden powers
Published: 2023-05-18 00:27:38

[Event loop](https://en.wikipedia.org/wiki/Event_loop) is at the core of every asynchronous framework. 

**Event loop** is  programming construct or a design pattern that waits for and dispatches events or messages in the program.

Most event loop implementation uses **callback queues** to enqueue callback and dequeue them as FIFO ( First-in first-out ). Also there is the **call-stack** yes  a stack data structure LIFO ( Last-in first-out ) which is also called function execution stack.

The way event loop, call-stack, callback queues ( events queues ) work together in an asynchronous program is when you await for a coroutines the coroutine will be enqueued into the event queue. When the call-stack is empty the event loop will dequeue future coroutine from the callback queue and push it into the callback stack and it will not be waited anymore and gets executed. 


But what if there is a call to change that ? What if in our event-driven API or real-time processing API the priority of our events are not created equally and we want some important events to be processed faster than less important ones ? 

We need an asynchronous framework which has Priority Queue instead of normal queue in the callback queue or we can decouple our system using RabbitMQ as it has message prioritization functionality.

Priority queue allows to enqueue and dequeue our data like normal however they are organized based on their given priority in descending or ascending order. 

Mentioning how to give messages priorities in RabbitMQ is too boring. Let's do the fun part, lets tweak a web framework !



FAST API & ASYNCIO to the rescue: 
asyncio provide powerful _priority queue_ which is _coroutine-safe_

_coroutine-safe_ is the concept of thread-safety for concurrency with coroutines.

Without further a due, lets tweak FastAPI

```Python

import asyncio

from fastapi import FastAPI

app = FastAPI()

# Create a priority queue with a custom comparison function
event_queue =  asyncio.PriorityQueue()

@app.on_event("startup")
async def startup_event():
    # Start a background task that processes events from the priority queue
    asyncio.create_task(process_events())

async def process_events():
    while True:
        # Wait for the next event from the priority queue
        _, event = await event_queue.get()
        
        # Process the event
        print(f"Processing event: {event}")
        
        # Mark the event as complete
        event_queue.task_done()
        print("task done")

@app.get("/")
async def read_root():
 # Add an event to the priority queue with a low priority (high number)
    await event_queue.put((10, "Low-priority event"))
      # Add an event to the priority queue with a low priority (high number)
    await event_queue.put((10, "Low-priority event"))
      # Add an event to the priority queue with a low priority (high number)
    await event_queue.put((2, "2 High-priority event"))
    await event_queue.put((10, "Low-priority event"))
      # Add an event to the priority queue with a low priority (high number)
    await event_queue.put((10, "Low-priority event"))
    # Add an event to the priority queue with a high priority (low number)
    await event_queue.put((1, " 1 High-priority event"))
    
    
    return {"message": "Events added to priority queue"}

```

when we send the following request GET http://localhost:8000

The output: 

Processing event:  1 High-priority event
task done
Processing event: 2 High-priority event
task done
Processing event: Low-priority event
task done
Processing event: Low-priority event
task done
Processing event: Low-priority event
task done
Processing event: Low-priority event
task done

what exactly happened ? This is not the FastAPI we know ?

Basically we changed the behavior of the event loop:

Now our event stack is not a queue as FIFO

SO know through our entire web service we have the complete control over the priority of processing of the events in the entire application.

our event stack is priority queue in which the event with the highest priority get pushed first by the event loop to the execution stack.

**Where this is useful ? ** 
Real-time data processing will be enhanced if the event queue is a priority queue. This is because a priority queue ensures that high-priority tasks are executed first, which can significantly improve the performance and responsiveness of the application. 

For example, an online multiplayer game that requires real-time communication between players would benefit from a priority queue. The game server could prioritize incoming player actions and updates over less critical tasks, ensuring that the game runs smoothly and without delay. 

Similarly, a financial trading application that needs to process high-frequency market data in real-time would also benefit from a priority queue. The application could prioritize incoming market data updates over less critical tasks, ensuring that trades are executed quickly and accurately. 


In sum , any application that requires real-time processing or time-sensitive tasks would benefit from a priority queue in the event loop.


However, it could also lead to unexpected behavior if the priorities are not set correctly or if certain events are given too high of a priority. It is important to carefully consider the impact of such a change and thoroughly test any modifications made to the event queue.


This is just an experiment but would love to hear your feedback !

Peace,

Ahmed,