notebookvb
This commit is contained in:
@@ -31,6 +31,72 @@ def get_medicus_connection():
|
||||
return fdb.connect(dsn=dsn, user="SYSDBA", password="masterkey", charset="win1250")
|
||||
|
||||
|
||||
class ReconnectingConnection:
|
||||
"""Obal nad fdb.Connection, který se sám znovu připojí, když spojení umře.
|
||||
|
||||
Dlouho běžící procesy (např. MCP server) drží jedno spojení od startu.
|
||||
To se rozpadne, když:
|
||||
* se notebook uspí/hibernuje (TCP socket odumře), nebo
|
||||
* na serveru proběhne denní gbak restore (Firebird zabije stará spojení).
|
||||
Výsledkem je `SQLCODE -902 Error writing data to the connection`.
|
||||
|
||||
Tato třída ověří před každým použitím, že spojení žije, a když ne,
|
||||
tiše ho znovu naváže. Volající kód používá .cursor()/.commit() beze změny.
|
||||
"""
|
||||
|
||||
def __init__(self, connect_fn=get_medicus_connection):
|
||||
self._connect = connect_fn
|
||||
self._conn = None
|
||||
|
||||
def _alive(self):
|
||||
if self._conn is None:
|
||||
return False
|
||||
try:
|
||||
cur = self._conn.cursor()
|
||||
cur.execute("SELECT 1 FROM RDB$DATABASE")
|
||||
cur.fetchone()
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def _ensure(self):
|
||||
if not self._alive():
|
||||
if self._conn is not None:
|
||||
try:
|
||||
self._conn.close()
|
||||
except Exception:
|
||||
pass
|
||||
self._conn = None
|
||||
self._conn = self._connect()
|
||||
return self._conn
|
||||
|
||||
def cursor(self):
|
||||
return self._ensure().cursor()
|
||||
|
||||
def commit(self):
|
||||
return self._ensure().commit()
|
||||
|
||||
def rollback(self):
|
||||
if self._conn is not None:
|
||||
return self._conn.rollback()
|
||||
|
||||
def close(self):
|
||||
if self._conn is not None:
|
||||
try:
|
||||
self._conn.close()
|
||||
finally:
|
||||
self._conn = None
|
||||
|
||||
def __getattr__(self, name):
|
||||
# ostatní atributy/metody proxy na živé spojení
|
||||
return getattr(self._ensure(), name)
|
||||
|
||||
|
||||
def get_medicus_connection_reconnecting():
|
||||
"""Vrátí spojení s automatickým reconnectem (vhodné pro dlouho běžící procesy)."""
|
||||
return ReconnectingConnection(get_medicus_connection)
|
||||
|
||||
|
||||
def get_medicus_db():
|
||||
"""Vrátí MedicusDB instanci s připojením podle názvu počítače."""
|
||||
conn = get_medicus_connection()
|
||||
|
||||
Reference in New Issue
Block a user