fix(seeders): switch GDELT GKG queries to single-theme fan-out + URL|Loc dedup (#3852)#3853
Conversation
…dedup v1 GKG GeoJSON only accepts one theme tag per call, and the previous free-text keyword queries weren't matching GDELT's tag-based index, returning non-filtered events which is useless for the usecase. Fan out both seeders (ais-relay positive events, seed-unrest-events) across themes, merge into a shared locationMap, and dedup by article URL across calls so multi-theme articles don't inflate counts. Also fix param casing (QUERY/MAXROWS) and add a urltone > 5 gate for the positive-events path. The unrest seeder now tolerates partial theme failures and only throws if all calls fail.
|
@shubham1206agra is attempting to deploy a commit to the World Monitor Team on Vercel. A member of the Team first needs to authorize it. |
|
@koala73 This is how I came up with themes which can give maximum throughput. GDELT GKG GeoJSON v1 — Positive-tone yield by themeProbed via
Note
Selected for production POSITIVE_QUERIES (6 themes)Balances absolute positive volume vs. precision; covers the 6 classifier categories:
Note Used AI to generate this formatted text |
Greptile SummaryThis PR fixes two GDELT GKG seeders that were sending free-text keyword queries the v1 API doesn't index well, replacing them with single-theme fan-out calls (one request per theme tag), fixing
Confidence Score: 3/5The unrest seeder will throw a ReferenceError on every successful run, silently discarding all aggregated events — this path needs a fix before merging. The scripts/seed-unrest-events.mjs — the post-loop console.log references a block-scoped variable from the loop Important Files Changed
Sequence DiagramsequenceDiagram
participant S as Seeder
participant G as GDELT GKG v1 API
participant R as Redis / Store
Note over S: seed-unrest-events.mjs
loop for each theme in [PROTEST, STRIKE, VIOLENT_UNREST]
S->>G: "GET ?QUERY=THEME&MAXROWS=2500"
G-->>S: GeoJSON features
S->>S: skip if fUrl in seenUrls
S->>S: merge into shared locationMap
S->>S: add fUrl to seenUrls
Note over S: wait 5.5s (rate limit)
end
S->>S: "filter count >= 5"
S->>R: store aggregated events
Note over S: ais-relay.cjs (positive events)
loop for each theme in [SOC_INNOVATION, EDUCATION, MEDICAL, TOURISM, ...]
S->>G: "GET ?QUERY=THEME&MAXROWS=500"
G-->>S: GeoJSON features
S->>S: skip if url in seenUrls
S->>S: "skip if urltone <= 5"
S->>S: merge into local locationMap
S->>S: add url to seenUrls
Note over S: wait 5.5s (rate limit)
end
S->>S: "filter count >= 3, dedup by name"
S->>R: store positive events
|
Update const POSITIVE_TONE_MIN to POSITIVE_TONE_THRESHOLD to better reflect the usage of the constant Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
|
I have tried switching to https://blog.gdeltproject.org/gdelt-geo-2-0-api-debuts/, but the API is 404'ing for me. |
Code Review — switch GDELT GKG queries to single-theme fan-out + URL dedupThe core diagnosis (param casing + single-theme constraint) is sound and the partial-failure handling is a genuine improvement. But the PR ships non-trivial new logic with zero test changes, and one existing locked contract is broken. 🔴 Blocking
🟡 Should fix
🟢 Minor / notes
VerdictRight root cause and reasonable structure, but not mergeable as-is: it breaks an existing test and adds substantial untested logic. Update |
|
@koala73 Thanks for the review. But can you confirm if the positive themes are fine with you? |
|
Let me address #3853 (comment) and I will let you know when this is ready |
…ution GKG v1 emits one feature per (article, location), so URL-only dedup collapses multi-location articles into a single location. Key dedup on (url, lat/lon bucket) instead, and resolve the URL via the same multi-field walk (extractGdeltSourceUrls / gkgFeatureUrl) used for source attribution — features carrying only source_url were bypassing dedup entirely. Lower POSITIVE_TONE_THRESHOLD from 5 → 2. Live volume check showed > 5 yielded ~1 positive event vs ~9 at > 2; the panel was going effectively empty. Add test coverage for the fan-out contract introduced in this PR: counts merge across themes at the same location, partial-failure tolerance (one theme dies, others still aggregate), all-themes-fail throws lastError, composite-key dedup preserves multi-location articles, and source_url-only features are deduped across themes.
@koala73 Please see the following table for confirmation
|
|
@koala73 This is ready for 2nd round of review |
Re-review (after fan-out/dedup updates)Thanks for the revisions — the earlier blocking items are resolved. Verified by checking out the PR head and running ✅ Resolved
🟡 Should fix — new CI-time regressionThe inter-theme rate-limit delay at if (i > 0) await new Promise((r) => setTimeout(r, 5_500)); // GDELT rate limitThe proxy-retry path has 🟢 Minor / nits
VerdictCore logic is correct and now well-tested on the unrest side. Recommend adding the inter-theme delay test seam before merge (66 s of CI sleep is a real cost the PR's own tests incur); the rest are nits. |
The unrest fan-out previously hardcoded a 5.5s setTimeout between theme calls, which forced fan-out tests to wait real-time (~11s each). Pull _sleep and _jitter out of _proxyOpts (same defaults pattern fetchGdelt- ViaProxy uses), so tests can pass noSleep/noJitter and run instantly. Production pacing is now 1.5-3s jittered between themes. Also clean up test koala73#6's stale assertion messages — calls === 4 now documents the breakdown ("theme 1: 1 throw + 1 retry; themes 2,3: 1 call each"), and "Fifteen mentions" is corrected to 11 (composite dedup blocks the two shared URLs across themes: 5 + 3 + 3). Adds a /11 reports/ match to lock the post-dedup count.
|
@koala73 Thanks for the review. I have made the changes |
|
@koala73 This is ready for review |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Summary
Fixes #3852
Root issue: GDELT v1 GKG GeoJSON only accepts one theme tag per call and uses uppercase
QUERY/MAXROWS. The previous free-text keyword queries (protest OR riot OR ...,breakthrough OR discovery OR ...) weren't matching GDELT's tag-based index well, and sending the unfiltered response without any errors.Both GDELT GKG seeders moved from free-text keyword queries to single-theme fan-out, since v1 GKG only accepts one theme tag per call and uses uppercase
QUERY/MAXROWSparams.scripts/ais-relay.cjs (positive events):
SOC_INNOVATION,EDUCATION,MEDICAL,TOURISM,WB_1765_CULTURE_HERITAGE_AND_SUSTAINABLE_TOURISM,PEACEKEEPING.QUERY/MAXROWS).urltone > 2gate so only positive-tone articles pass.seenUrlLocs) so a multi-theme article doesn't inflate counts.scripts/seed-unrest-events.mjs (unrest events):
PROTEST,STRIKE,VIOLENT_UNREST.locationMap, merging counts and source URLs.Type of change
Affected areas
/api/*)Checklist
api/rss-proxy.jsallowlist (if adding feeds)npm run typecheck)Screenshots