Repository navigation
Isolate and bound feed and server ingestion - #507
Merged
Merged
Conversation
Large feeds queued one task per event on the default queue, starving
periodic jobs and letting any number of sources ingest at once.
- Separate queues: `ingest` (feed fetches, server pulls/pushes and their
follow-ups) on its own ingest-worker, `maintenance` for periodic jobs;
beat entries expire after their interval so a backlog can't pile up.
- Ingestion runs (app/services/ingest_runs.py): one run per source,
`ingest.max_concurrent_runs` admitted at once (others wait as queued),
`ingest.paused` runtime switch, events drained from a Redis list in
batches by a couple of self-requeueing tasks per run.
- A watchdog restarts or closes runs that stopped making progress.
- GET/DELETE /feeds/{id}/run and /servers/{id}/run to see and cancel a
run; disabling or deleting a feed/server cancels its run.
- Timeouts on feed downloads and remote MISP requests.
- Reactor dispatch warms a cold trigger cache instead of failing open
for every ingested attribute.
Refs #506
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OpenAPI changesAdded endpoints
Modified endpoints
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #507 +/- ##
==========================================
+ Coverage 88.56% 88.74% +0.18%
==========================================
Files 292 295 +3
Lines 34272 35114 +842
==========================================
+ Hits 30354 31163 +809
- Misses 3918 3951 +33 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The maintenance queue mixed jobs that run every 15-300 seconds with rebuilds that walk everything for minutes to hours (correlations, indicators, lookup cache, warninglist loads and re-evaluations, galaxies, taxonomies, retention). On a single-process worker a rebuild held up indicator syncs, EDL refreshes and the ingest watchdog. Those now run on `bulk`, served by a new bulk-worker, so operators change their worker command once along with the ingest split. Refs #506 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run status and controls:
- Feeds and servers lists show each source's run in progress or how its
last one ended; a feed's or server's page shows the run's progress, a
Cancel button, and the last run's outcome and error. Pages poll only
while a run is active or was just triggered.
- Runtime settings: an ingest form (concurrent runs, pause).
- Diagnostics: a Queues card with messages waiting per Celery queue, the
workers consuming each (a queue with none is flagged), and every run in
progress or waiting, from the new GET /diagnostics/queues.
Cancelling closes a run at once. It used to wait for its drain tasks,
which can sit behind a long ingest queue (minutes of "cancelling").
Runs now get an id that their drain tasks carry, so a task left over
from a cancelled run stops instead of draining a later run of the same
source. The "cancelling" status is gone.
Feed events:
- The MISP feed explorer marks each event as ingested from this feed,
newer in the feed, already here from another source, or not ingested,
links to the local copy, and counts how many were ingested.
- The feed row's magnifying glass opens the explorer, as on servers (it
showed only counts, and nothing linked to the explorer).
- A feed's page lists its 10 most recently ingested events, from the new
GET /feeds/{id}/events, with a link to all of them in Explore
(?range=all opens Explore without its default 30-day time range).
- Events record created_at, when first written here: their timestamp is
the source's own.
Refs #506
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The add and edit feed forms open with only what a new feed needs. MISP feed rules and indicator scoring (now under "Advanced settings") are collapsed, each header summarising what applies: "Last 30 days", "None: every event is fetched", "score modifier -10", ... so nothing is hidden by being collapsed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Objects a bulk ingest creates are handled in batches of 500
(handle_created_objects) once the ingest is done, like attributes,
instead of one task each: a large feed queued tens of thousands of
messages ahead of the drain tasks.
- A run opened before runs had ids keeps being drained: its drain tasks,
and the watchdog's, skipped it after an upgrade until it expired.
- Tests for GET /feeds/{id}/events and the MISP feed explorer's local
copies; docs for both and for created_at.
- Feed forms: a separate, collapsed "Advanced settings" section holds
authentication and indicator scoring, its header summarising what is
set. MISP server and organisation forms collapse their indicator
scoring the same way.
Closes #506
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The update interval and "fetch immediately" move out of Feed Settings into their own Schedule section. - "MISP Feed Rules" becomes "Filtering rules", on the forms and the feed page, which says when nothing is filtered out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements #506: isolation, bounded ingestion, and the operator controls and visibility (API and UI).
Why
A MISP feed fetch or server pull queued one task per event on the default queue. A few large sources could bury periodic jobs (indicator sync, warninglists, EDL refreshes, retention...) for hours, and nothing limited how many sources ingested at once.
What changes
Queues
ingest: feed fetches, server pulls/pushes and their follow-ups (attribute/object handlers, correlation, reactor dispatches coming from ingestion). Served by a newingest-workerservice.maintenance: frequent periodic jobs (indicator and lookup cache sync, EDL refreshes, recent warninglist hits, the ingest watchdog...), served by the existingworker(--queues=celery,maintenance).bulk: rebuilds and reloads that walk everything and run for minutes to hours (correlations, indicator and lookup cache rebuilds, warninglist loads and full re-evaluations, galaxies, taxonomies, retention). Served by a newbulk-worker, so a rebuild can't hold up the frequent jobs.Ingestion runs (
app/services/ingest_runs.py, Redis-backed)ingest.max_concurrent_runs(runtime setting, default 2) runs ingest at once. The others wait asqueuedand retry every minute.ingest.pausedholds all of them.revive_stalled_ingest_runs) restarts or closes runs with no progress for 45 minutes, for example after a drain task was killed mid-batch.API
GET /feeds/{id}/runandGET /servers/{id}/runreturn the current and last run: status, totals, pending count, error.DELETEon the same paths cancels a run. Disabling or deleting a feed or server also cancels its run.UI
ingestform: concurrent runs, pause.GET /diagnostics/queues).Feed event views
GET /feeds/{id}/events), with a link to all of them in Explore.?range=allopens Explore without its default 30-day range.created_at, when first written here; theirtimestampis the source's own. It is inopensearch/mappings/misp-events.json, and existing indices pick it up through dynamic mapping.Feed forms
Robustness
handle_created_objects), like attributes. Before, one task per object (about 18,000 in 40 minutes for CIRCL OSINT) queued ahead of the drain tasks.reactor_dispatchrebuilds a cold trigger cache first. The gate fails open when the cache is missing (after a Redis restart, for example), and each ingested attribute then queued a dispatch.Deployment
docker-compose.ymladdsingest-worker(--queues=ingest,stop_grace_period: 5mso it can finish its batch on shutdown) andbulk-worker(--queues=bulk).maintenance,ingestandbulktoo, for example a single worker with--queues=celery,maintenance,ingest,bulk; see the README.Testing
tests/services/test_ingest_runs.pyand reactor cache-warming tests, and a/diagnostics/queuestest.GET /feeds/{id}/eventsand the explorer's local copies (they use the database, so CI runs them; not run locally).mainin the same stack: an oversized warninglist index on a 512 MB OpenSearch heap, and nomodulesservice.queued;DELETE /feeds/{id}/runcancelled a run;Closes #506
🤖 Generated with Claude Code