mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-23 17:47:31 +00:00
exceptions below are raised when running python3 with "-X dev": Traceback (most recent call last): File "...\electrum\electrum\util.py", line 999, in run_with_except_hook run_original(*args2, **kwargs2) File "...\Python38\lib\threading.py", line 870, in run self._target(*self._args, **self._kwargs) File "...\electrum\electrum\sql_db.py", line 55, in run_sql future.set_result(result) File "...\Python38\lib\asyncio\base_events.py", line 721, in call_soon self._check_thread() File "...\Python38\lib\asyncio\base_events.py", line 758, in _check_thread raise RuntimeError( RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one Traceback (most recent call last): File "...\electrum\electrum\gui\qt\main_window.py", line 3009, in closeEvent self.clean_up() # File "...\electrum\electrum\gui\qt\main_window.py", line 3026, in clean_up self.gui_object.close_window(self) File "...\electrum\electrum\gui\qt\__init__.py", line 340, in close_window self.daemon.stop_wallet(window.wallet.storage.path) File "...\electrum\electrum\daemon.py", line 518, in stop_wallet wallet.stop() File "...\electrum\electrum\wallet.py", line 344, in stop self.lnworker.stop() File "...\electrum\electrum\lnworker.py", line 602, in stop super().stop() File "...\electrum\electrum\lnworker.py", line 273, in stop self.listen_server.close() File "...\Python38\lib\asyncio\base_events.py", line 337, in close self._loop._stop_serving(sock) File "...\Python38\lib\asyncio\proactor_events.py", line 849, in _stop_serving future.cancel() File "...\Python38\lib\asyncio\windows_events.py", line 80, in cancel return super().cancel() File "...\Python38\lib\asyncio\base_events.py", line 721, in call_soon self._check_thread() File "...\Python38\lib\asyncio\base_events.py", line 758, in _check_thread raise RuntimeError( RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one
67 lines
2.1 KiB
Python
67 lines
2.1 KiB
Python
import os
|
|
import concurrent
|
|
import queue
|
|
import threading
|
|
import asyncio
|
|
import sqlite3
|
|
|
|
from .logging import Logger
|
|
from .util import test_read_write_permissions
|
|
|
|
|
|
def sql(func):
|
|
"""wrapper for sql methods"""
|
|
def wrapper(self: 'SqlDB', *args, **kwargs):
|
|
assert threading.currentThread() != self.sql_thread
|
|
f = asyncio.Future()
|
|
self.db_requests.put((f, func, args, kwargs))
|
|
return f
|
|
return wrapper
|
|
|
|
|
|
class SqlDB(Logger):
|
|
|
|
def __init__(self, asyncio_loop: asyncio.BaseEventLoop, path, commit_interval=None):
|
|
Logger.__init__(self)
|
|
self.asyncio_loop = asyncio_loop
|
|
self.path = path
|
|
test_read_write_permissions(path)
|
|
self.commit_interval = commit_interval
|
|
self.db_requests = queue.Queue()
|
|
self.sql_thread = threading.Thread(target=self.run_sql)
|
|
self.sql_thread.start()
|
|
|
|
def filesize(self):
|
|
return os.stat(self.path).st_size
|
|
|
|
def run_sql(self):
|
|
self.logger.info("SQL thread started")
|
|
self.conn = sqlite3.connect(self.path)
|
|
self.logger.info("Creating database")
|
|
self.create_database()
|
|
i = 0
|
|
while self.asyncio_loop.is_running():
|
|
try:
|
|
future, func, args, kwargs = self.db_requests.get(timeout=0.1)
|
|
except queue.Empty:
|
|
continue
|
|
try:
|
|
result = func(self, *args, **kwargs)
|
|
except BaseException as e:
|
|
self.asyncio_loop.call_soon_threadsafe(future.set_exception, e)
|
|
continue
|
|
if not future.cancelled():
|
|
self.asyncio_loop.call_soon_threadsafe(future.set_result, result)
|
|
# note: in sweepstore session.commit() is called inside
|
|
# the sql-decorated methods, so commiting to disk is awaited
|
|
if self.commit_interval:
|
|
i = (i + 1) % self.commit_interval
|
|
if i == 0:
|
|
self.conn.commit()
|
|
# write
|
|
self.conn.commit()
|
|
self.conn.close()
|
|
self.logger.info("SQL thread terminated")
|
|
|
|
def create_database(self):
|
|
raise NotImplementedError()
|