Added change batches, so clients can catch up on changed opportunities
Every save that stores new opportunities or new releases records them in a change batch (migration 00008: opportunity_change_batches and opportunity_change_batch_opportunities; the opportunities table is unchanged), as does every change of marks. A batch is named by a random SHA-256 hash, so it can't be guessed, and ordered by its created_at, which is kept strictly increasing even if the clock goes back. GET /api/opportunities pages now carry the newest batch, read before the page, and GET /api/opportunities?changed_after=<batch> returns every opportunity changed since that batch, unpaged, with the newest batch it includes. Offset and limit can't be combined with it, and an unknown batch is 410 Gone, telling the client to reload the whole list. OpportunitiesUpdated now carries its save's batch, and a "large" flag: over 50 opportunities, new and updated are left empty and only the summary counts them, so a big catch-up no longer sends tens of thousands of UUIDs.
This commit is contained in:
1 parent
51d6470649
commit
155b84caea
13 files changed
+699
-29
No files matched your search
@@ -277,3 +277,45 @@ SELECT *
|
||||
FROM opportunity_marks
|
||||
WHERE uuid IN (?)
|
||||
ORDER BY uuid`
|
||||
|
||||
// ---------- opportunity_change_batches ----------
|
||||
|
||||
// insertChangeBatch records a batch, returning its id. The created_at
|
||||
// argument must be later than every stored batch's (see recordChangeBatch).
|
||||
const insertChangeBatch = `
|
||||
INSERT INTO opportunity_change_batches (hash, created_at)
|
||||
VALUES (?, ?)
|
||||
RETURNING id`
|
||||
|
||||
// selectLatestChangeBatch reads the newest batch into a changeBatch.
|
||||
const selectLatestChangeBatch = `
|
||||
SELECT *
|
||||
FROM opportunity_change_batches
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1`
|
||||
|
||||
// selectChangeBatchByHash reads the batch with a hash into a changeBatch.
|
||||
const selectChangeBatchByHash = `
|
||||
SELECT * FROM opportunity_change_batches WHERE hash = ?`
|
||||
|
||||
// ---------- opportunity_change_batch_opportunities ----------
|
||||
|
||||
// insertChangeBatchOpportunity adds an opportunity to a batch.
|
||||
const insertChangeBatchOpportunity = `
|
||||
INSERT INTO opportunity_change_batch_opportunities (batch_id, opportunity_uuid)
|
||||
VALUES (?, ?)
|
||||
ON CONFLICT DO NOTHING`
|
||||
|
||||
// selectOpportunitiesChangedBetween reads, into opportunityRows, the
|
||||
// opportunities in the batches created after the first argument and at or
|
||||
// before the second, once each, ordered as ListOpportunities orders them.
|
||||
const selectOpportunitiesChangedBetween = `
|
||||
SELECT t.*
|
||||
FROM opportunities t
|
||||
WHERE t.uuid IN (
|
||||
SELECT bo.opportunity_uuid
|
||||
FROM opportunity_change_batch_opportunities bo
|
||||
JOIN opportunity_change_batches b ON b.id = bo.batch_id
|
||||
WHERE b.created_at > ? AND b.created_at <= ?
|
||||
)
|
||||
ORDER BY t.latest_release_date DESC, t.uuid`
|
||||
Reference in new issue
Block a user