Patró gestió connexions a base de dades

Ja he parlat alguna altra vegada de SQLAlchemy.

Com sabreu els que us hi heu dedicat alguna vegada, la gestió de les connexions a les bases de dades és un punt crític a les aplicacions amb diversos usuaris simultanis. Bé, és extensible a qualssevol recursos escassos.

Una solució que proposen (i deixen ben clar que no és l’única) és la següent:

from contextlib import contextmanager

sessions = sessionmaker (...) 

@contextmanager
def entorn_sessio ():
    sessio = sessions()
    try:
        yield sessio
        sessio.commit()
    except:
        sessio.rollback()
        raise
    finally:
        sessio.close() 

def fer_feina():
    # En acabar-se el WITH el bloc torna a entorn_sessio, just després del YIELD. 
    # Farà el commit
    # Si hi ha un error rebrem l'excepció
    # En tot cas allibera la connexió a la base de dades

    try:
        with entorn_sessio() as una_sessio:
            # El que hi ha dins del WITH pot fer l'accés a base de dades

            llibre_nou = Llibre(autor="Pierre Lemaître", titol="Couleurs de l'incendie")
            una_sessio.add (llibre_nou)

    except:
        # Tractar els errors des del punt de vista funcional, sense amoïnar-se per la connexió a la base de dades

    # I aquí seguim fent coses que no necessiten base de dades
    fer_mes_feina_sense_base_dades ()

L’he trobat molt elegant i a més m’agrada perquè:

  • Queda clar en quin bloc es fa accés a base de dades (el que és dins del with). Això convida a fer-lo curt i, si no ho és, a repensar-ho una mica.
  • Fa una gestió global del recurs (l’accés a base de dades) de forma bastant còmoda, que em sembla fàcil d’estandarditzar en tota una aplicació o en un equip de treball.
  • En cap cas es queden connexions obertes (si se segueix el patró a tot arreu, és clar).
  • M’ha permès aprofundir en el yield (no l’havia fet servir mai, encara… i és que m’agrada el Python, però vaig aprendre a programar amb BASIC i Pascal, que són molt tradicionals).

L’he començat a fer servir per una aplicació d’ús personal, amb una variant: un “entorn_sessio” per a actualitzacions (com el que hi ha a l’exemple de dalt) i un altre només per consultes, que incondicionalment fa un rollback() al final.

Si bé aquest mètode em sembla bo, no hi ha solució universal a aquests problemes. I gairebé és tan important assegurar-se que dins d’una aplicació es fa a tot arreu de la mateixa manera com la correcció de la solució per ella mateixa.

22/3/2019: Exemple retocat.

Deixa un comentari

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *

Aquest lloc utilitza Akismet per reduir els comentaris brossa. Apreneu com es processen les dades dels comentaris.