Try and catch block for dbRebuild (#2047)

* Try and catch block for dbRebuild

* Use self.log.error and not logging

* Use self.log.error and not logging in SiteStorage also

* Check if the rebuild is working
This commit is contained in:
Lola Dam 2019-06-23 14:21:50 +02:00 committed by ZeroNet
parent 9a267ffcaf
commit 753396ac0c
8 changed files with 55 additions and 23 deletions

View file

@ -786,9 +786,10 @@ class UiWebsocketPlugin(object):
if "ADMIN" not in permissions: if "ADMIN" not in permissions:
return self.response(to, "You don't have permission to run this command") return self.response(to, "You don't have permission to run this command")
result = self.site.storage.rebuildDb() try:
self.site.storage.rebuildDb()
except Exception as err:
return self.response(to, {"error": str(err)})
if not result:
return self.response(to, {"error": "Failed to rebuild database"})
return self.response(to, "ok") return self.response(to, "ok")

View file

@ -814,6 +814,7 @@ window.initScrollable = function () {
this.tag.find("#button-dbrebuild").off("click touchend").on("click touchend", (function(_this) { this.tag.find("#button-dbrebuild").off("click touchend").on("click touchend", (function(_this) {
return function() { return function() {
_this.wrapper.notifications.add("done-dbrebuild", "info", "Database rebuilding...."); _this.wrapper.notifications.add("done-dbrebuild", "info", "Database rebuilding....");
_this.wrapper.ws.cmd("dbRebuild", [], function(response) { _this.wrapper.ws.cmd("dbRebuild", [], function(response) {
if (response !== "ok") { if (response !== "ok") {

View file

@ -1,7 +1,7 @@
import time import time
import os import os
from Db.Db import Db from Db.Db import Db, DbTableError
from Config import config from Config import config
from Plugin import PluginManager from Plugin import PluginManager
from Debug import Debug from Debug import Debug
@ -14,7 +14,10 @@ class ContentDb(Db):
self.foreign_keys = True self.foreign_keys = True
try: try:
self.schema = self.getSchema() self.schema = self.getSchema()
try:
self.checkTables() self.checkTables()
except DbTableError:
pass
self.log.debug("Checking foreign keys...") self.log.debug("Checking foreign keys...")
foreign_key_error = self.execute("PRAGMA foreign_key_check").fetchone() foreign_key_error = self.execute("PRAGMA foreign_key_check").fetchone()
if foreign_key_error: if foreign_key_error:
@ -26,7 +29,10 @@ class ContentDb(Db):
Db.__init__(self, {"db_name": "ContentDb", "tables": {}}, path) Db.__init__(self, {"db_name": "ContentDb", "tables": {}}, path)
self.foreign_keys = True self.foreign_keys = True
self.schema = self.getSchema() self.schema = self.getSchema()
try:
self.checkTables() self.checkTables()
except DbTableError:
pass
self.site_ids = {} self.site_ids = {}
self.sites = {} self.sites = {}

View file

@ -48,6 +48,10 @@ gevent.spawn(dbCleanup)
gevent.spawn(dbCommitCheck) gevent.spawn(dbCommitCheck)
atexit.register(dbCloseAll) atexit.register(dbCloseAll)
class DbTableError(Exception):
def __init__(self, message, table):
super().__init__(message)
self.table = table
class Db(object): class Db(object):
@ -256,15 +260,18 @@ class Db(object):
# Check schema tables # Check schema tables
for table_name, table_settings in self.schema.get("tables", {}).items(): for table_name, table_settings in self.schema.get("tables", {}).items():
try: try:
indexes = table_settings.get("indexes", [])
version = table_settings.get("schema_changed", 0)
changed = cur.needTable( changed = cur.needTable(
table_name, table_settings["cols"], table_name, table_settings["cols"],
table_settings.get("indexes", []), version=table_settings.get("schema_changed", 0) indexes, version=version
) )
if changed: if changed:
changed_tables.append(table_name) changed_tables.append(table_name)
except Exception as err: except Exception as err:
self.log.error("Error creating table %s: %s" % (table_name, Debug.formatException(err))) self.log.error("Error creating table %s: %s" % (table_name, Debug.formatException(err)))
return False raise DbTableError(err, table_name)
#return False
self.log.debug("Db check done in %.3fs, changed tables: %s" % (time.time() - s, changed_tables)) self.log.debug("Db check done in %.3fs, changed tables: %s" % (time.time() - s, changed_tables))
if changed_tables: if changed_tables:

View file

@ -708,7 +708,10 @@ class Site(object):
# Rebuild DB # Rebuild DB
if new_site.storage.isFile("dbschema.json"): if new_site.storage.isFile("dbschema.json"):
new_site.storage.closeDb() new_site.storage.closeDb()
try:
new_site.storage.rebuildDb() new_site.storage.rebuildDb()
except Exception as err:
self.log.error(err)
return new_site return new_site

View file

@ -11,7 +11,7 @@ import gevent.event
import util import util
from util import SafeRe from util import SafeRe
from Db.Db import Db from Db.Db import Db, DbTableError
from Debug import Debug from Debug import Debug
from Config import config from Config import config
from util import helper from util import helper
@ -73,15 +73,21 @@ class SiteStorage(object):
schema = self.getDbSchema() schema = self.getDbSchema()
db_path = self.getPath(schema["db_file"]) db_path = self.getPath(schema["db_file"])
if not os.path.isfile(db_path) or os.path.getsize(db_path) == 0: if not os.path.isfile(db_path) or os.path.getsize(db_path) == 0:
try:
self.rebuildDb() self.rebuildDb()
except Exception as err:
self.log.error(err)
pass
if self.db: if self.db:
self.db.close() self.db.close()
self.db = self.openDb(close_idle=True) self.db = self.openDb(close_idle=True)
try:
changed_tables = self.db.checkTables() changed_tables = self.db.checkTables()
if changed_tables: if changed_tables:
self.rebuildDb(delete_db=False) # TODO: only update the changed table datas self.rebuildDb(delete_db=False) # TODO: only update the changed table datas
except sqlite3.OperationalError:
pass
return self.db return self.db
@ -138,11 +144,10 @@ class SiteStorage(object):
self.event_db_busy = gevent.event.AsyncResult() self.event_db_busy = gevent.event.AsyncResult()
self.log.info("Creating tables...") self.log.info("Creating tables...")
changed_tables = self.db.checkTables()
if not changed_tables: # raise DbTableError if not valid
# It failed self.db.checkTables()
# "Error creating table..."
return False
cur = self.db.getCursor() cur = self.db.getCursor()
cur.logging = False cur.logging = False
s = time.time() s = time.time()
@ -195,7 +200,10 @@ class SiteStorage(object):
except sqlite3.DatabaseError as err: except sqlite3.DatabaseError as err:
if err.__class__.__name__ == "DatabaseError": if err.__class__.__name__ == "DatabaseError":
self.log.error("Database error: %s, query: %s, try to rebuilding it..." % (err, query)) self.log.error("Database error: %s, query: %s, try to rebuilding it..." % (err, query))
try:
self.rebuildDb() self.rebuildDb()
except sqlite3.OperationalError:
pass
res = self.db.cur.execute(query, params) res = self.db.cur.execute(query, params)
else: else:
raise err raise err

View file

@ -20,3 +20,6 @@ class TestSiteStorage:
# Subdir # Subdir
assert set(site.storage.list("data-default")) == set(["data.json", "users"]) assert set(site.storage.list("data-default")) == set(["data.json", "users"])
def testDbRebuild(self, site):
assert site.storage.rebuildDb()

View file

@ -238,8 +238,11 @@ class Actions(object):
logging.info("Rebuilding site sql cache: %s..." % address) logging.info("Rebuilding site sql cache: %s..." % address)
site = SiteManager.site_manager.get(address) site = SiteManager.site_manager.get(address)
s = time.time() s = time.time()
try:
site.storage.rebuildDb() site.storage.rebuildDb()
logging.info("Done in %.3fs" % (time.time() - s)) logging.info("Done in %.3fs" % (time.time() - s))
except Exception as err:
logging.error(err)
def dbQuery(self, address, query): def dbQuery(self, address, query):
from Site.Site import Site from Site.Site import Site