Skip to content

Fix DBhandler exception when get_settings fails#65

Open
giosava94 wants to merge 2 commits intomainfrom
64-dbhandler-raise-exception-if-settings-is-invalid
Open

Fix DBhandler exception when get_settings fails#65
giosava94 wants to merge 2 commits intomainfrom
64-dbhandler-raise-exception-if-settings-is-invalid

Conversation

@giosava94
Copy link
Copy Markdown
Member

@giosava94 giosava94 commented Nov 25, 2025

Now, when get_settings raises a ValueError, the get_logger function catches that error and applies a default value.

The DBHandler's constructor initializes the _logger and _engine instance variables to None by default. This way, when the instance creation fails, the DBHandler disposes the engine connection only if _engine is not None (execution of the __del__ method).

@giosava94 giosava94 requested a review from jacogasp November 25, 2025 11:59
@giosava94 giosava94 linked an issue Nov 25, 2025 that may be closed by this pull request
@sonarqubecloud
Copy link
Copy Markdown

Comment thread fed_mgr/db.py
self._engine = None

self._settings = get_settings()
self._logger = get_logger(__class__.__name__, self._settings.LOG_LEVEL)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Qual è il vantaggio di questa cosa? Il problema non sta in get_settings? Che sia dentro alla funzione get_logger credo importi poco

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La funzione get_settings c'era già nell'init, non l'ho aggiunta. Semplicemente era dopo get_logger. L'ho messa prima di get_logger per 2 motivi:

  • se ci sono problemi con settings, crasha prima di chiamare get_logger, invece di dover gestire l'eccezione nel get_logger e poi cmq crashare.
  • avendo qui un get_settings funzionante, posso passare direttamente log_level (risparmiando una seconda chiamata a get_settings)

Copy link
Copy Markdown
Contributor

@jacogasp jacogasp Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm non mi piace però, perché così devi passare il log level ogni volta che chiami get_logger, e a quel punto puoi trovarti con due log level diversi. Io lo terrei dentro punto e basta.

Invece che ci sta che crashi alla 37, però se get_settings() crasha mi sta bene che crashi pure DBHandler.__init__

A questo punto il problema è che viene chiamato il distruttore __del__ anche se è crashato __init__, che non ha molto senso a mio avviso

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

il log_level è rimasto opzionale. Se non è passato si prendo quello di settings (come era prima di questa modifica)

Comment thread fed_mgr/db.py
self._logger = get_logger(__class__.__name__)
self._initialized = False
self._logger = None
self._engine = None
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perché sono diventati opzionali? Li lascerei non opzionali, al più si deve rompere l'app se engine non è stato in grado di costruirlo

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Il problema non è nella costruzione ma nell'eliminazione del DBHandler (vedi sotto)

Comment thread fed_mgr/db.py
"""Disconnect from the database."""
self._logger.info("Disconnecting from database")
self._engine.dispose()
if self._engine is not None:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vedi sopra, non vedo perché self._engine dovrebbe essere none

Copy link
Copy Markdown
Member Author

@giosava94 giosava94 Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Se non metti self._engine = None e l'app crasha quando carica i settings o il logger, lui in ogni caso esegue il __del__. Quindi, se non metti self._engine = None nell'__init__ il __del__ crasha perchè non trova la variabile self._engine.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ma infatti il problema sta qui. Deve crashare init e non deve essere essere chiamato il distruttore __del__. L'app deve essere già morta prima ancora di arrivare a __del__

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

L'init crasha infatti. Ma cmq viene eseguito il del. Se vuoi rimettiti sul main e fai solo la modifica che proponi (sul get_logger). Vedrai che ti da problemi.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://godbolt.org/z/3MshM74za maledetto python, dobbiamo sistemare questa cosa che è terribile

Copy link
Copy Markdown
Member Author

@giosava94 giosava94 Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Questo vuol dire aggiugere un try except in più nel delete (cosa che tu stesso hai detto essere poco efficiente). Tenere l'if con il valore a none fa la stessa cosa e funziona.

Copy link
Copy Markdown
Member Author

@giosava94 giosava94 Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adotterei la tecnica del try/except nel distruttore. Butterei via tutte le modifiche di questa pr e terrei solo l'esempio di stackoverflow

Fai come meglio credi. Io non concordo (su vari commenti) ma chiudi pure la PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Il try except è poco efficiente se lo usi al posto di un "if" e ne fai tanti. Dal momento che qui muore, non è un problema, e di solito questa cosa è buona norma fatta nei distruttori proprio perché ci possono essere eccezioni in fase di distruzione

https://baltig.infn.it/cnafsd/storm-tape/-/blob/main/src/profiler.hpp?ref_type=heads#L102

Lo so che con l'if funziona lo stesso, però implicitamente mi hai detto che DBHandler può esistere senza engine, mentre i due devono avere lo stesso identico lifespan (uno non esiste senza l'altro)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Se fosse un linguaggio compilato/fortemente tipato, ora DBHandler.get_engine() ritornerebbe un optional<Engine>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adotterei la tecnica del try/except nel distruttore. Butterei via tutte le modifiche di questa pr e terrei solo l'esempio di stackoverflow

Fai come meglio credi. Io non concordo (su vari commenti) ma chiudi pure la PR.

No non volevo buttare via la PR, volevo solo fare revert e mettere il try/execept nel distruttore del db handler :)

In realtà il try/except direi che comunque ci vuole dentro get_settings()

Comment thread fed_mgr/logger.py

"""
try:
settings = get_settings()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non mi fa impazzire questo try/except fatto così, anche perché non sappiamo cosa succede se get_settings fallisce per errori diversi da ValueError.

Farei qualcosa del tipo

def get_logger(name):
    formatter = "..."
    stream_handler.setFormatter(formatter)
    logger = logging.getLogger(name)
    logger.addHandler(stream_handler)
    try:
      settings = get_settings()
      logger.setLevel(level=log_level)
    except e:
       logger.setLevel(DEFAULT_LEVEL)
       logger.exception(e)
    return logger

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DBHandler raise exception if settings is invalid

2 participants