monitor user file modifications & reload if necessary

This commit is contained in:
Jakob Ketterl 2021-02-08 17:24:59 +01:00
parent d9578cc5f4
commit ed6594401c

View File

@ -1,5 +1,6 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from owrx.config import CoreConfig from owrx.config import CoreConfig
from datetime import datetime, timezone
import json import json
import hashlib import hashlib
import os import os
@ -125,19 +126,33 @@ class UserList(object):
return UserList.sharedInstance return UserList.sharedInstance
def __init__(self): def __init__(self):
self.users = self._loadUsers() self.file_modified = None
self.users = {}
def refresh(self):
if self.file_modified is None or self._getUsersFileModifiedTimestamp() > self.file_modified:
logger.debug("reloading users from disk due to file modification")
self.users = self._loadUsers()
def _getUsersFile(self): def _getUsersFile(self):
config = CoreConfig() config = CoreConfig()
return "{data_directory}/users.json".format(data_directory=config.get_data_directory()) return "{data_directory}/users.json".format(data_directory=config.get_data_directory())
def _getUsersFileModifiedTimestamp(self):
return datetime.fromtimestamp(os.path.getmtime(self._getUsersFile()), timezone.utc)
def _loadUsers(self): def _loadUsers(self):
usersFile = self._getUsersFile() usersFile = self._getUsersFile()
# to avoid concurrency issues and problems when parsing errors occur:
# get early, store late
modified = self._getUsersFileModifiedTimestamp()
try: try:
with open(usersFile, "r") as f: with open(usersFile, "r") as f:
users_json = json.load(f) users_json = json.load(f)
return {u.name: u for u in [self._jsonToUser(d) for d in users_json]} users = {u.name: u for u in [self._jsonToUser(d) for d in users_json]}
self.file_modified = modified
return users
except FileNotFoundError: except FileNotFoundError:
return {} return {}
except json.JSONDecodeError: except json.JSONDecodeError:
@ -156,12 +171,13 @@ class UserList(object):
def store(self): def store(self):
usersFile = self._getUsersFile() usersFile = self._getUsersFile()
users = [u.toJson() for u in self.users.values()] users = [u.toJson() for u in self.values()]
try: try:
with open(usersFile, "w") as f: with open(usersFile, "w") as f:
json.dump(users, f, indent=4) json.dump(users, f, indent=4)
except Exception: except Exception:
logger.exception("error while writing users file %s", usersFile) logger.exception("error while writing users file %s", usersFile)
self.refresh()
def _getUsername(self, user): def _getUsername(self, user):
if isinstance(user, User): if isinstance(user, User):
@ -178,22 +194,27 @@ class UserList(object):
del self[self._getUsername(user)] del self[self._getUsername(user)]
def __delitem__(self, key): def __delitem__(self, key):
self.refresh()
if key not in self.users: if key not in self.users:
raise KeyError("User {user} doesn't exist".format(user=key)) raise KeyError("User {user} doesn't exist".format(user=key))
del self.users[key] del self.users[key]
self.store() self.store()
def __getitem__(self, item): def __getitem__(self, item):
self.refresh()
return self.users[item] return self.users[item]
def __contains__(self, item): def __contains__(self, item):
self.refresh()
return item in self.users return item in self.users
def __setitem__(self, key, value): def __setitem__(self, key, value):
self.refresh()
if key in self.users: if key in self.users:
raise KeyError("User {user} already exists".format(user=key)) raise KeyError("User {user} already exists".format(user=key))
self.users[key] = value self.users[key] = value
self.store() self.store()
def values(self): def values(self):
self.refresh()
return self.users.values() return self.users.values()