Skip to content

Commit 7f01809

Browse files
author
BharatVe
committed
Updated scripts for issue 145. Add time stamp and logging function.
1 parent ce50950 commit 7f01809

3 files changed

Lines changed: 53 additions & 33 deletions

File tree

publications/templates/data.html

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ <h2 class="py-2">OpenAPI UI</h2>
3939

4040
<h2 class="py-2">Download Publication Data</h2>
4141
<ul class="list-unstyled mb-4">
42-
{% if geojson_size %}
42+
{% if last_geojson %}
4343
<li class="mb-3">
4444
<div class="d-flex align-items-center">
4545
<a class="btn btn-primary btn-sm" href="{% url 'optimap:download_geojson' %}">
@@ -48,28 +48,32 @@ <h2 class="py-2">Download Publication Data</h2>
4848
(<a href="https://geojson.org/" target="_blank" class="ms-2 small">GeoJSON spec</a>)
4949
</div>
5050
<div class="small text-muted mt-1">
51-
File size: {{ geojson_size }}
51+
File: {{ last_geojson }}{% if geojson_size %} &middot; Size: {{ geojson_size }}{% endif %}
5252
</div>
5353
</li>
5454
{% endif %}
5555

56-
{% if geopackage_size %}
56+
{% if last_gpkg %}
5757
<li>
5858
<div class="d-flex align-items-center">
5959
<a class="btn btn-primary btn-sm" href="{% url 'optimap:download_geopackage' %}">
6060
Download GeoPackage
61-
</a>
61+
</a>
6262
(<a href="https://www.geopackage.org/" target="_blank" class="ms-2 small">GeoPackage spec</a>)
6363
</div>
6464
<div class="small text-muted mt-1">
65-
File size: {{ geopackage_size }}
65+
File: {{ last_gpkg }}{% if geopackage_size %} &middot; Size: {{ geopackage_size }}{% endif %}
6666
</div>
6767
</li>
6868
{% endif %}
6969
</ul>
7070
<p class="small text-muted text-center mb-0">
7171
Data dumps run every {{ interval }} hour{{ interval|pluralize }}.<br>
72-
Last updated: {{ last_updated|naturaltime }}
72+
{% if last_updated %}
73+
Last updated: {{ last_updated|naturaltime }}
74+
{% else %}
75+
No dumps have been generated yet.
76+
{% endif %}
7377
</p>
7478

7579
</div>

publications/views.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ def loginres(request):
188188
def privacy(request):
189189
return render(request, 'privacy.html')
190190

191-
192191
@never_cache
193192
def data(request):
194193
"""
@@ -197,33 +196,46 @@ def data(request):
197196
cache_dir = Path(tempfile.gettempdir()) / "optimap_cache"
198197
cache_dir.mkdir(exist_ok=True)
199198

200-
# locate latest dumps
199+
# scan for existing dumps
201200
geojson_files = sorted(cache_dir.glob('optimap_data_dump_*.geojson'), reverse=True)
202-
gpkg_files = sorted(cache_dir.glob('optimap_data_dump_*.gpkg'), reverse=True)
203-
204-
last_geo = geojson_files[0] if geojson_files else None
205-
last_gpkg = gpkg_files[0] if gpkg_files else None
201+
gpkg_files = sorted(cache_dir.glob('optimap_data_dump_*.gpkg'), reverse=True)
202+
203+
last_geo = geojson_files[0] if geojson_files else None
204+
last_gzip = Path(str(last_geo) + ".gz") if last_geo else None
205+
last_gpkg = gpkg_files[0] if gpkg_files else None
206+
207+
# — Supervisor check: ensure all dump file times are within 1 hour
208+
mtimes = []
209+
for p in (last_geo, last_gzip, last_gpkg):
210+
if p and p.exists():
211+
mtimes.append(p.stat().st_mtime)
212+
if mtimes and (max(mtimes) - min(mtimes) > 3600):
213+
ts_map = {
214+
p.name: datetime.fromtimestamp(p.stat().st_mtime, get_default_timezone())
215+
for p in (last_geo, last_gzip, last_gpkg) if p and p.exists()
216+
}
217+
logger.warning("Data dump timestamps differ by >1h: %s", ts_map)
206218

207219
# humanized sizes
208-
geojson_size = humanize.naturalsize(last_geo.stat().st_size, binary=True) if last_geo else None
209-
gpkg_size = humanize.naturalsize(last_gpkg.stat().st_size, binary=True) if last_gpkg else None
220+
geojson_size = humanize.naturalsize(last_geo.stat().st_size, binary=True) if last_geo else None
221+
geopackage_size = humanize.naturalsize(last_gpkg.stat().st_size, binary=True) if last_gpkg else None
210222

211-
# last updated timestamp
223+
# last updated timestamp (using JSON file)
212224
if last_geo:
213225
ts = last_geo.stat().st_mtime
214226
last_updated = datetime.fromtimestamp(ts, get_default_timezone())
215227
else:
216228
last_updated = None
217229

218230
return render(request, 'data.html', {
219-
'geojson_size': geojson_size,
220-
'geopackage_size': gpkg_size,
221-
'interval': settings.DATA_DUMP_INTERVAL_HOURS,
222-
'last_updated': last_updated,
223-
'last_geojson': last_geo.name if last_geo else None,
224-
'last_gpkg': last_gpkg.name if last_gpkg else None,
231+
'geojson_size': geojson_size,
232+
'geopackage_size': geopackage_size,
233+
'interval': settings.DATA_DUMP_INTERVAL_HOURS,
234+
'last_updated': last_updated,
235+
'last_geojson': last_geo.name if last_geo else None,
236+
'last_gpkg': last_gpkg.name if last_gpkg else None,
225237
})
226-
238+
227239
def Confirmationlogin(request):
228240
return render(request, 'confirmation_login.html')
229241

tests/test_geo_data.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,21 @@
22
import json
33
import tempfile
44
import gzip
5-
import json
6-
tempfile
75
from datetime import datetime, timedelta
86
from django.test import TestCase
97
from django.core.serializers import serialize
108
import fiona
11-
gzip
129
from django.urls import reverse
1310
from django.conf import settings
1411
import re
1512
from publications.models import Publication
1613
from publications.views import generate_geopackage
17-
from publications.tasks import regenerate_geojson_cache, generate_data_dump_filename, cleanup_old_data_dumps
14+
from publications.tasks import (
15+
regenerate_geojson_cache,
16+
regenerate_geopackage_cache,
17+
generate_data_dump_filename,
18+
cleanup_old_data_dumps,
19+
)
1820
from pathlib import Path
1921

2022
class GeoDataAlternativeTestCase(TestCase):
@@ -101,12 +103,9 @@ def test_data_endpoint(self):
101103
self.assertEqual(response.status_code, 200, "Data endpoint should return status 200")
102104
content = response.content.decode()
103105
self.assertIn(f"Data dumps run every {settings.DATA_DUMP_INTERVAL_HOURS} hour", content)
104-
# find the most recent JSON dump
105106
cache_dir = Path(tempfile.gettempdir()) / 'optimap_cache'
106107
dumps = sorted(cache_dir.glob('optimap_data_dump_*.geojson'), reverse=True)
107108
self.assertTrue(dumps, "At least one data dump should exist for Last updated check")
108-
last = dumps[0]
109-
mtime = last.stat().st_mtime
110109
self.assertIn("Last updated:", content)
111110

112111
def test_download_geojson_gzip(self):
@@ -122,12 +121,12 @@ def test_download_geopackage_endpoint(self):
122121
url = reverse('optimap:download_geopackage')
123122
response = self.client.get(url)
124123
self.assertEqual(response.status_code, 200, "GeoPackage endpoint should return 200")
125-
self.assertEqual(response['Content-Type'], 'application/geopackage+sqlite3', "Content-Type should be application/geopackage+sqlite3")
124+
self.assertEqual(response['Content-Type'], 'application/geopackage+sqlite3',
125+
"Content-Type should be application/geopackage+sqlite3")
126126
self.assertRegex(response['Content-Disposition'], r'optimap_data_dump_.*\.gpkg')
127127

128128
def test_regenerate_geojson_cache_creates_files(self):
129129
cache_dir = Path(tempfile.gettempdir()) / 'optimap_cache'
130-
# clean out all existing dump files
131130
for f in cache_dir.glob('optimap_data_dump_*'):
132131
f.unlink()
133132

@@ -162,9 +161,8 @@ def test_download_geopackage(self):
162161
self.assertEqual(response['Content-Type'], 'application/geopackage+sqlite3')
163162
self.assertRegex(response['Content-Disposition'], r'optimap_data_dump_.*\.gpkg')
164163

165-
def test_data_page_hides_links_when_missing_cache(self):
164+
def test_data_page_hides_and_shows_links_correctly(self):
166165
cache_dir = Path(tempfile.gettempdir()) / 'optimap_cache'
167-
# clear only our dynamic dumps
168166
for f in cache_dir.glob('optimap_data_dump_*'):
169167
f.unlink()
170168

@@ -178,3 +176,9 @@ def test_data_page_hides_links_when_missing_cache(self):
178176
content = response.content.decode()
179177
self.assertIn('Download GeoJSON', content)
180178
self.assertNotIn('Download GeoPackage', content)
179+
180+
regenerate_geopackage_cache()
181+
response = self.client.get(reverse('optimap:data'))
182+
content = response.content.decode()
183+
self.assertIn('Download GeoJSON', content)
184+
self.assertIn('Download GeoPackage', content)

0 commit comments

Comments
 (0)