0

I have an azure functions application(python) which connects to snowflake database(creates a dbconnection object), executes query and returns the results and it has been working fine. The only challenge is time it takes to return the query. It creates the dbconnection object everytime when it is invoked.

Question: Is it possible to pool the connection using functions app ( considering the functions app is stateless)

SunilS
  • 2,030
  • 5
  • 34
  • 62
  • Does this answer your question? [SQL connection pooling in Azure Functions](https://stackoverflow.com/questions/41208524/sql-connection-pooling-in-azure-functions) – Sajeetharan Jan 15 '20 at 07:50
  • No, It doesn't, since functions are essentially stateless. Every invocation of function calls the connection object again. Who maintains the connection pool in these scenarios. – SunilS Jan 15 '20 at 07:56

1 Answers1

1

The short answer is YES, here is my sample code of Azure Function with HTTP trigger as below.

import logging

import azure.functions as func

def inc(n):
    while True:
        n += 1
        yield n

count = inc(0)

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    return func.HttpResponse(f"Count: {count.__next__()}!")

I declared a global variable count with the value of a generator inc(0) outside the function main, then I can get an increased count response as the figure below.

enter image description here

It's the same as my another answer for the SO thread Azure use python flask framework for function app.

So I think it's indeed to realize a connection pool in Azure Functions, such as using snowflakedb/snowflake-sqlalchemy to create a connection pool for Snowflake database in Python outside the function main of Azure Function, as the code below by refering to the SQLAlchemy document Connection Pooling.

import logging
import azure.functions as func
from sqlalchemy import create_engine
import sqlalchemy.pool as pool

engine = create_engine(
    'snowflake://{user}:{password}@{account}/'.format(
        user='<your_user_login_name>',
        password='<your_password>',
        account='<your_account_name>',
    )
)

def getconn():
    connection = engine.connect()
    return connection

mypool = pool.QueuePool(getconn, max_overflow=10, pool_size=5)

def main(req: func.HttpRequest) -> func.HttpResponse:
    try:
        conn = mypool.connect()
        # Do the code what you want, such as
        # cursor = conn.cursor()
        # cursor.execute("select foo")
        ....
    finally:
        conn.close()
    return func.HttpResponse(f"......")

The explaination for the code above is that as below.

  1. Azure Functions for Python start up to compile the source code from top to bottom and load its bytecode to memory, then the mypool object will be invoked from memory following the main function be triggered until mypool removed from memory after idle long time.
  2. Next time to trigger the main function after idle, a new mypool object will be created and continous to do as above.
Peter Pan
  • 23,476
  • 4
  • 25
  • 43
  • There is one catch .. Ideally, getconn() should not be called on each invocation. If you start logging, you will see taht getconn() being called on each involcation – SunilS Jan 15 '20 at 16:24