diff options
author | Daniel Schadt <kingdread@gmx.de> | 2023-03-30 21:19:46 +0200 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2023-03-30 21:41:47 +0200 |
commit | 60a1585a37bfee43e3d6c7cac002eeee85768c5f (patch) | |
tree | e9bb6b163e5d6858f18c5b69aa8833b51d470507 | |
parent | a2aaf098ca5ac897a5e0e1b2302acaf0562f8aad (diff) | |
download | fietsboek-60a1585a37bfee43e3d6c7cac002eeee85768c5f.tar.gz fietsboek-60a1585a37bfee43e3d6c7cac002eeee85768c5f.tar.bz2 fietsboek-60a1585a37bfee43e3d6c7cac002eeee85768c5f.zip |
check if data version matches at startup
This might be helpful to see some errors early.
-rw-r--r-- | fietsboek/__init__.py | 30 | ||||
-rw-r--r-- | fietsboek/updater/__init__.py | 46 |
2 files changed, 75 insertions, 1 deletions
diff --git a/fietsboek/__init__.py b/fietsboek/__init__.py index 41e8a04..ee7d8b7 100644 --- a/fietsboek/__init__.py +++ b/fietsboek/__init__.py @@ -14,6 +14,7 @@ Content ------- """ import importlib.metadata +import logging from pathlib import Path from typing import Callable, Optional @@ -33,9 +34,12 @@ from . import transformers from .data import DataManager from .pages import Pages from .security import SecurityPolicy +from .updater import Updater, UpdateState __VERSION__ = importlib.metadata.version("fietsboek") +LOGGER = logging.getLogger(__name__) + def locale_negotiator(request: Request) -> Optional[str]: """Negotiates the right locale to use. @@ -88,12 +92,36 @@ def maintenance_mode( return tween -def main(_global_config, **settings): +def check_update_state(config_uri: str): + """Checks the update state of the data, and logs a warning if there is a + mismatch. + + :param config_uri: Path to the configuration file. + """ + updater = Updater(config_uri) + updater.load() + state = updater.state() + + if state == UpdateState.OUTDATED: + LOGGER.warning( + "The data seems to be outdated - make sure to run the fietsupdate migrations!" + ) + elif state == UpdateState.TOO_NEW: + LOGGER.warning("The data seems to be too new, make sure to update the code accordingly!") + elif state == UpdateState.UNKNOWN: + LOGGER.warning("Could not determine version state of the data - check `fietsupdate status`") + + +def main(global_config, **settings): """This function returns a Pyramid WSGI application.""" # Avoid a circular import by not importing at the top level # pylint: disable=import-outside-toplevel,cyclic-import from .views.tileproxy import TileRequester + # In tests this isn't passed, so guard against it + if "__file__" in global_config: + check_update_state(global_config["__file__"]) + parsed_config = mod_config.parse(settings) settings["jinja2.newstyle"] = True diff --git a/fietsboek/updater/__init__.py b/fietsboek/updater/__init__.py index fa7f5c6..5faa805 100644 --- a/fietsboek/updater/__init__.py +++ b/fietsboek/updater/__init__.py @@ -1,5 +1,6 @@ """Updating (data migration) logic for fietsboek.""" import datetime +import enum import importlib.resources import importlib.util import logging @@ -50,6 +51,26 @@ class Down(UpdateScript): """ +class UpdateState(enum.Enum): + """State of the applied updates. + + This represents a "summary" of the output that ``fietsupdate status`` + produces. + """ + + OKAY = enum.auto() + """Everything is good, the data is up to date.""" + + OUTDATED = enum.auto() + """The data is outdated, the update process should be run.""" + + TOO_NEW = enum.auto() + """The data contains revisions that are not known to Fietsboek yet.""" + + UNKNOWN = enum.auto() + """The data version could not be determined.""" + + class Updater: """A class that implements the updating logic. @@ -284,6 +305,31 @@ class Updater: return revision_id in self._transitive_versions() return revision_id in self._reverse_versions() | set(self.current_versions()) + def state(self) -> UpdateState: + """Checks the update state of the instance. + + This returns a condensed version of what ``fietsupdate status`` + outputs. + + :return: The update state of the data. + """ + state = UpdateState.OKAY + current = self.current_versions() + heads = self.heads() + if current: + for i in current: + if not self.exists(i): + state = UpdateState.TOO_NEW + else: + return UpdateState.UNKNOWN + updates = set(heads) - set(current) + if updates: + if state != UpdateState.OKAY: + # We are both too new and too old, so something is pretty wrong + return UpdateState.UNKNOWN + return UpdateState.OUTDATED + return state + class UpdateScript: """Represents an update script.""" |