Implemented WAL journal mode for database

Some of the waitress code has been overwritten to make this work (at `backend.db.ThreadedTaskDispatcher`). The `handler_thread` function has been changed so that when the thread shuts down, the database connection for the thread is also closed (this _has_ to happen _in the thread that the connection is for/from_). The `shutdown` function opens and closes a database connection at the end, which triggers the checkpoint of the journal, writing everything to the db file and removing the `-wal` and `-shm` temporary db files.
This commit is contained in:
CasVT
2023-06-30 22:11:18 +02:00
parent 361efbd264
commit 8c5e34caee
4 changed files with 35 additions and 10 deletions

View File

@@ -1,5 +1,5 @@
# Byte-compiled / optimized / DLL files
__pycache__/
**/__pycache__/
*.py[cod]
*$py.class
@@ -129,14 +129,13 @@ dmypy.json
.pyre/
# Database
*.db
**/*.db
# VS code
*.code-workspace
.vscode/
# Docker
Dockerfile
.dockerignore
docker-compose.yml
@@ -146,7 +145,7 @@ docker-compose.yml
.github/
# Various files
*.md
**/*.md
LICENSE
# Tests

View File

@@ -1,6 +1,7 @@
# syntax=docker/dockerfile:1
FROM python:3.8-slim-buster
STOPSIGNAL SIGINT
WORKDIR /app

View File

@@ -11,7 +11,7 @@ from flask import Flask, render_template, request
from waitress.server import create_server
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from backend.db import DBConnection, close_db, setup_db
from backend.db import DBConnection, ThreadedTaskDispatcher, close_db, setup_db
from frontend.api import api, api_prefix, reminder_handler
from frontend.ui import ui
@@ -90,7 +90,7 @@ def MIND() -> None:
app = _create_app()
with app.app_context():
if isfile(_folder_path('db', 'Noted.db')):
move(_folder_path('db', 'Noted.db'), _folder_path('db', 'MIND.db'))
move(_folder_path('db', 'Noted.db'), _folder_path(*DB_FILENAME))
db_location = _folder_path(*DB_FILENAME)
makedirs(dirname(db_location), exist_ok=True)
DBConnection.file = db_location
@@ -98,10 +98,11 @@ def MIND() -> None:
reminder_handler.find_next_reminder()
# Create waitress server and run
server = create_server(app, host=HOST, port=PORT, threads=THREADS)
dispatcher = ThreadedTaskDispatcher()
dispatcher.set_thread_count(THREADS)
server = create_server(app, _dispatcher=dispatcher, host=HOST, port=PORT, threads=THREADS)
print(f'MIND running on http://{HOST}:{PORT}{URL_PREFIX}')
server.run()
print(f'\nShutting down MIND...')
# Stopping thread
reminder_handler.stop_handling()

View File

@@ -7,8 +7,11 @@ from time import time
from typing import Union
from flask import g
from waitress.task import ThreadedTaskDispatcher as OldThreadedTaskDispatcher
__DATABASE_VERSION__ = 5
from backend.custom_exceptions import AccessUnauthorized, UserNotFound
__DATABASE_VERSION__ = 6
class Singleton(type):
_instances = {}
@@ -20,6 +23,18 @@ class Singleton(type):
return cls._instances[i]
class ThreadedTaskDispatcher(OldThreadedTaskDispatcher):
def handler_thread(self, thread_no: int) -> None:
super().handler_thread(thread_no)
i = f'{DBConnection}{current_thread()}'
if i in Singleton._instances and not Singleton._instances[i].closed:
Singleton._instances[i].close()
def shutdown(self, cancel_pending: bool = True, timeout: int = 5) -> bool:
print('Shutting down MIND...')
super().shutdown(cancel_pending, timeout)
DBConnection(20.0).close()
class DBConnection(Connection, metaclass=Singleton):
file = ''
@@ -177,13 +192,22 @@ def migrate_db(current_db_version: int) -> None:
COMMIT;
""")
current_db_version = 5
if current_db_version == 5:
# V5 -> V6
from backend.users import User
try:
User('User1', 'Password1').delete()
except (UserNotFound, AccessUnauthorized):
pass
return
def setup_db() -> None:
"""Setup the database
"""
cursor = get_db()
cursor.execute("PRAGMA journal_mode = wal;")
cursor.executescript("""
CREATE TABLE IF NOT EXISTS users(