aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2025-04-24 17:55:41 +0200
committerGuilhem Moulin <guilhem@fripost.org>2025-05-01 15:29:55 +0200
commit3edce255b3010244ab5d7fae59cbda11926f50f1 (patch)
tree8fd463f21f3d5da0d2edcef4b6e3a234aea52a14
parentad38438a0b980ee816e1573bf18362e72345fa4d (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.py47
-rwxr-xr-xwebmap-import37
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