diff options
author | Guilhem Moulin <guilhem@fripost.org> | 2025-04-24 17:55:41 +0200 |
---|---|---|
committer | Guilhem Moulin <guilhem@fripost.org> | 2025-05-01 15:29:55 +0200 |
commit | 3edce255b3010244ab5d7fae59cbda11926f50f1 (patch) | |
tree | 8fd463f21f3d5da0d2edcef4b6e3a234aea52a14 | |
parent | ad38438a0b980ee816e1573bf18362e72345fa4d (diff) |
importSources(): Return either success, error, or no change.
That way we can detect when the import of all layers are no-op (besides
changing last_updated) and exit gracefully.
-rw-r--r-- | import_source.py | 47 | ||||
-rwxr-xr-x | webmap-import | 37 |
2 files changed, 53 insertions, 31 deletions
diff --git a/import_source.py b/import_source.py index c4cb96f..647c79e 100644 --- a/import_source.py +++ b/import_source.py @@ -28,6 +28,7 @@ from pathlib import Path from datetime import datetime, timedelta, UTC from typing import Any, Final, Optional import traceback +from enum import Enum, unique from hashlib import sha256 import struct @@ -435,6 +436,13 @@ def listArchiveMembers(namelist : list[str], logging.debug('Ignoring archive member %s', name) return members +@unique +class ImportStatus(Enum): + """Return value for importSources(): success, error, or no-change.""" + IMPORT_SUCCESS = 0 + IMPORT_ERROR = 1 + IMPORT_NOCHANGE = 255 + # pylint: disable-next=dangerous-default-value def importSources(dso : gdal.Dataset, lyr : ogr.Layer, sources : dict[str,Any] = {}, @@ -442,7 +450,7 @@ def importSources(dso : gdal.Dataset, lyr : ogr.Layer, extent : ogr.Geometry|None = None, dsoTransaction : bool = False, lyrcache : ogr.Layer|None = None, - force : bool = False) -> bool: + force : bool = False) -> ImportStatus: """Clear lyr and import source layers to it.""" layername = lyr.GetName() @@ -462,7 +470,7 @@ def importSources(dso : gdal.Dataset, lyr : ogr.Layer, layername) lyrTransaction = False - rv = True + rv = ImportStatus.IMPORT_NOCHANGE now = datetime.now().astimezone() fingerprint = sha256() fingerprint_map = fingerprintLayerDefn(fingerprint, lyr) @@ -482,20 +490,24 @@ def importSources(dso : gdal.Dataset, lyr : ogr.Layer, dso.FlushCache() fingerprint = fingerprint.digest() - if lyrcache is not None: - if not updateLayerCache(layername=layername, - cache=lyrcache, - ds=dso, lyr=lyr, - force=force, - lyrTransaction=lyrTransaction, - last_updated=now, - fingerprint=fingerprint): - if isinstance(lyrTransaction, bool): - # the transaction on lyr was already rolled back - lyrTransaction = False + if lyrcache is None: + rv = ImportStatus.IMPORT_SUCCESS + elif updateLayerCache(layername=layername, + cache=lyrcache, + ds=dso, lyr=lyr, + force=force, + lyrTransaction=lyrTransaction, + last_updated=now, + fingerprint=fingerprint): + rv = ImportStatus.IMPORT_SUCCESS + else: + rv = ImportStatus.IMPORT_NOCHANGE + if isinstance(lyrTransaction, bool): + # the transaction on lyr was already rolled back + lyrTransaction = False except Exception: # pylint: disable=broad-exception-caught - rv = False + rv = ImportStatus.IMPORT_ERROR if isinstance(lyrTransaction, str): query = 'ROLLBACK TO ' + lyrTransaction logging.exception('Exception occured within transaction: %s', query) @@ -523,17 +535,16 @@ def importSources(dso : gdal.Dataset, lyr : ogr.Layer, try: dso.ExecuteSQL(query) except Exception: # pylint: disable=broad-exception-caught - rv = False + rv = ImportStatus.IMPORT_ERROR logging.exception('Could not execute SQL: %s', query) elif isinstance(lyrTransaction, bool) and lyrTransaction: try: if lyr.CommitTransaction() != ogr.OGRERR_NONE: - rv = False + rv = ImportStatus.IMPORT_ERROR logging.error('Could not commit transaction') except Exception: # pylint: disable=broad-exception-caught - rv = False + rv = ImportStatus.IMPORT_ERROR logging.exception('Could not commit transaction on layer "%s"', layername) - return rv # pylint: disable-next=dangerous-default-value diff --git a/webmap-import b/webmap-import index c801b6d..6f514a9 100755 --- a/webmap-import +++ b/webmap-import @@ -64,7 +64,8 @@ from import_source import ( openOutputDS, createOutputLayer, validateOutputLayer, - importSources + importSources, + ImportStatus ) def setFieldIf(cond : bool, @@ -256,9 +257,8 @@ def processOutputLayer(ds : gdal.Dataset, extent : ogr.Geometry|None = None, dsTransaction : bool = False, lyrcache : ogr.Layer|None = None, - force : bool = False) -> bool: - """Process an output layer, and return a boolean indicating whether - the import was sucessful (or skipped), or not.""" + force : bool = False) -> ImportStatus: + """Process an output layer.""" logging.info('Processing output layer "%s"', layername) lyr = ds.GetLayerByName(layername) @@ -274,7 +274,7 @@ def processOutputLayer(ds : gdal.Dataset, lyrcache=lyrcache, cachedir=cachedir)): logging.info('Output layer "%s" is up to date, skipping', layername) - return True + return ImportStatus.IMPORT_NOCHANGE validateOutputLayer(lyr, srs=srs, options=layerdef['create']) @@ -661,15 +661,26 @@ def main() -> NoReturn: rv = 0 try: + r = ImportStatus.IMPORT_NOCHANGE for layername, layerdef in layers.items(): - if not processOutputLayer(dso, layername, layerdef, - srs=srs, - cachedir=cachedir, - extent=extent, - dsTransaction=dsoTransaction, - lyrcache=lyr_cache, - force=args.force): + r0 = processOutputLayer(dso, layername, layerdef, + srs=srs, + cachedir=cachedir, + extent=extent, + dsTransaction=dsoTransaction, + lyrcache=lyr_cache, + force=args.force) + if r0 == ImportStatus.IMPORT_ERROR: rv = 1 + if dsoTransaction: + dsoTransaction = False + logging.debug('Rolling back transaction') + # no need to catch the exception here + if dso.CommitTransaction() != ogr.OGRERR_NONE: + logging.error('Could not rollback transaction') + if r == ImportStatus.IMPORT_NOCHANGE and r0 == ImportStatus.IMPORT_SUCCESS: + r = ImportStatus.IMPORT_SUCCESS + logging.info('result = %s', str(r)) if sourcePathLocks is not None: releaseSourcePathLocks(sourcePathLocks) @@ -682,7 +693,6 @@ def main() -> NoReturn: rv = 1 except Exception: # pylint: disable=broad-exception-caught - rv = 1 if dsoTransaction: logging.exception('Exception occured within transaction, rolling back') try: @@ -692,6 +702,7 @@ def main() -> NoReturn: logging.exception('Could not rollback transaction') else: traceback.print_exc() + sys.exit(1) finally: lyr_cache = None |