Skip to content

Commit b56d56c

Browse files
committed
eventcounter-etag-based revalidation for geodata endpoints
1 parent 2f33fd5 commit b56d56c

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

lib/model/query/actees.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,9 @@ const provision = (species, parent) => ({ one }) =>
1616
one(sql`insert into actees (id, species, parent) values (${uuid()}, ${species}, ${(parent == null) ? null : parent.acteeId}) returning *`)
1717
.then(construct(Actee));
1818

19-
module.exports = { provision };
19+
const getEventCount = (acteeId) => ({ oneFirst }) => oneFirst(sql`
20+
SELECT coalesce(sum(evt_count), 0) FROM eventcounters WHERE "acteeId" = ${acteeId}
21+
`);
22+
23+
module.exports = { provision, getEventCount };
2024

lib/resources/geo-extracts.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
const { getOrNotFound } = require('../util/promise');
1111
const { Form } = require('../model/frames');
1212
const { Sanitize } = require('../util/param-sanitize');
13-
const { isTrue, json } = require('../util/http');
13+
const { isTrue, json, withEtag } = require('../util/http');
1414
const Problem = require('../util/problem');
1515

1616

@@ -37,13 +37,15 @@ module.exports = (service, endpoint) => {
3737

3838

3939
// Bulk endpoints
40-
service.get('/projects/:projectId/forms/:xmlFormId/submissions.geojson', endpoint.plain(async ({ Forms, GeoExtracts }, { auth, query, params }) => {
40+
service.get('/projects/:projectId/forms/:xmlFormId/submissions.geojson', endpoint.plain(async ({ Forms, GeoExtracts, Actees }, { auth, query, params }) => {
4141

4242
const form = await Forms.getByProjectAndXmlFormId(params.projectId, params.xmlFormId, Form.WithoutDef, Form.WithoutXml)
4343
.then(getOrNotFound)
4444
.then((foundForm) => auth.canOrReject('submission.list', foundForm));
4545

46-
return GeoExtracts.getSubmissionFeatureCollectionGeoJson(
46+
const acteeVersion = await Actees.getEventCount(form.acteeId);
47+
48+
const createResponse = () => GeoExtracts.getSubmissionFeatureCollectionGeoJson(
4749
form.id,
4850
Sanitize.queryParamToArray(query.submissionID),
4951
Sanitize.queryParamToArray(query.fieldpath),
@@ -53,15 +55,21 @@ module.exports = (service, endpoint) => {
5355
isTrue(query.deleted),
5456
Number.parseInt(query.limit, 10) || null,
5557
).then(json);
58+
59+
// Weak etag, as the order in the resultset is undefined.
60+
return withEtag(acteeVersion, createResponse, true);
5661
}));
5762

58-
service.get('/projects/:projectId/datasets/:datasetName/entities.geojson', endpoint.plain(async ({ Datasets, GeoExtracts }, { auth, query, params }) => {
63+
64+
service.get('/projects/:projectId/datasets/:datasetName/entities.geojson', endpoint.plain(async ({ Datasets, GeoExtracts, Actees }, { auth, query, params }) => {
5965

6066
const foundDataset = await Datasets.get(params.projectId, params.datasetName, true)
6167
.then(getOrNotFound)
6268
.then((dataset) => auth.canOrReject('entity.list', dataset));
6369

64-
return GeoExtracts.getEntityFeatureCollectionGeoJson(
70+
const acteeVersion = await Actees.getEventCount(foundDataset.acteeId);
71+
72+
const createResponse = () => GeoExtracts.getEntityFeatureCollectionGeoJson(
6573
foundDataset.id,
6674
Sanitize.queryParamToUuidArray(query.entityUUID, 'entityUUID'),
6775
Sanitize.queryParamToIntArray(query.creatorId, 'creatorId'),
@@ -70,6 +78,9 @@ module.exports = (service, endpoint) => {
7078
isTrue(query.deleted),
7179
Number.parseInt(query.limit, 10) || null,
7280
).then(json);
81+
82+
// Weak etag, as the order in the resultset is undefined.
83+
return withEtag(acteeVersion, createResponse, true);
7384
}));
7485

7586
};

0 commit comments

Comments
 (0)