(Core data): Restart when DB is inaccessible.

This commit is contained in:
2021-09-21 16:06:30 +03:00
parent ce3af79d3c
commit 73cceb0412
2 changed files with 38 additions and 0 deletions

View File

@@ -38,3 +38,10 @@ with conn:
log("Established connection.", "DB_INIT") log("Established connection.", "DB_INIT")
def reset_connection():
log("Re-establishing connection.", "DB_INIT", level=logging.DEBUG)
global conn
conn = psy.connect(conf.bot['database'], cursor_factory=DictLoggingCursor)
log("Re-established connection.", "DB_INIT")

View File

@@ -1,9 +1,14 @@
from __future__ import annotations from __future__ import annotations
import logging
import traceback
import contextlib import contextlib
from cachetools import LRUCache from cachetools import LRUCache
from typing import Mapping from typing import Mapping
import psycopg2
import asyncio
from meta import log, client
from utils.lib import DotDict from utils.lib import DotDict
from .connection import conn from .connection import conn
@@ -14,6 +19,25 @@ from .queries import insert, insert_many, select_where, update_where, upsert, de
tables: Mapping[str, Table] = DotDict() tables: Mapping[str, Table] = DotDict()
def _connection_guard(func):
"""
Query decorator that performs a client shutdown when the database isn't responding.
"""
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except (psycopg2.OperationalError, psycopg2.InterfaceError):
log("Critical error performing database query. Shutting down. "
"Exception traceback follows.\n{}".format(
traceback.format_exc()
),
context="DATABASE_QUERY",
level=logging.ERROR)
asyncio.create_task(client.close())
raise Exception("Critical error, database connection closed. Restarting client.")
return wrapper
class Table: class Table:
""" """
Transparent interface to a single table structure in the database. Transparent interface to a single table structure in the database.
@@ -27,6 +51,7 @@ class Table:
self.name = name self.name = name
tables[attach_as or name] = self tables[attach_as or name] = self
@_connection_guard
def select_where(self, *args, **kwargs): def select_where(self, *args, **kwargs):
with self.conn: with self.conn:
return select_where(self.name, *args, **kwargs) return select_where(self.name, *args, **kwargs)
@@ -35,26 +60,32 @@ class Table:
rows = self.select_where(*args, **kwargs) rows = self.select_where(*args, **kwargs)
return rows[0] if rows else None return rows[0] if rows else None
@_connection_guard
def update_where(self, *args, **kwargs): def update_where(self, *args, **kwargs):
with self.conn: with self.conn:
return update_where(self.name, *args, **kwargs) return update_where(self.name, *args, **kwargs)
@_connection_guard
def delete_where(self, *args, **kwargs): def delete_where(self, *args, **kwargs):
with self.conn: with self.conn:
return delete_where(self.name, *args, **kwargs) return delete_where(self.name, *args, **kwargs)
@_connection_guard
def insert(self, *args, **kwargs): def insert(self, *args, **kwargs):
with self.conn: with self.conn:
return insert(self.name, *args, **kwargs) return insert(self.name, *args, **kwargs)
@_connection_guard
def insert_many(self, *args, **kwargs): def insert_many(self, *args, **kwargs):
with self.conn: with self.conn:
return insert_many(self.name, *args, **kwargs) return insert_many(self.name, *args, **kwargs)
@_connection_guard
def update_many(self, *args, **kwargs): def update_many(self, *args, **kwargs):
with self.conn: with self.conn:
return update_many(self.name, *args, **kwargs) return update_many(self.name, *args, **kwargs)
@_connection_guard
def upsert(self, *args, **kwargs): def upsert(self, *args, **kwargs):
with self.conn: with self.conn:
return upsert(self.name, *args, **kwargs) return upsert(self.name, *args, **kwargs)