Feat/url checker - #988
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a URL-checking workflow in draft-api to scan article HTML for external links, verify them via HTTP HEAD, and take automated actions (update redirected URLs + add editor notes, or schedule revisions for broken/unreachable URLs). It also adds an internal endpoint intended for cron-based daily “washing” of a partitioned slice of the article corpus.
Changes:
- Added
UrlCheckerServiceto extract URLs from article content, perform HEAD checks, update redirected URLs, and addEditorNote/RevisionMetaas appropriate. - Added DB support for selecting the latest revision of articles by modulus partitioning (
article_id % modulus). - Added
POST /intern/check-urlsendpoint to run the checker for a given modulus slice (defaulting to “day-of-year” partitioning).
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| draft-api/src/test/scala/no/ndla/draftapi/TestEnvironment.scala | Adds a mocked UrlCheckerService to the shared test environment. |
| draft-api/src/test/scala/no/ndla/draftapi/service/UrlCheckerServiceTest.scala | New unit tests covering URL extraction, URL checking behavior, and draft update logic. |
| draft-api/src/main/scala/no/ndla/draftapi/service/UrlCheckerService.scala | New service implementing URL extraction, HEAD checks, redirect updates, and revision scheduling for broken URLs. |
| draft-api/src/main/scala/no/ndla/draftapi/repository/DraftRepository.scala | Adds getArticlesByModulus to fetch the latest revision per article for a modulus-selected slice. |
| draft-api/src/main/scala/no/ndla/draftapi/DraftApiProperties.scala | Adds UrlCheckDaysInYear configuration for partitioning. |
| draft-api/src/main/scala/no/ndla/draftapi/controller/InternController.scala | Adds POST /intern/check-urls endpoint to run the URL checker. |
| draft-api/src/main/scala/no/ndla/draftapi/ComponentRegistry.scala | Registers UrlCheckerService in the DI registry. |
| common/src/main/scala/no/ndla/common/model/NDLADate.scala | Adds plusMonths used for “revision one month ahead”. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /** POST /intern/check-urls | ||
| * | ||
| * Runs the URL checker for a slice of articles selected by modulus arithmetic on article_id. | ||
| * | ||
| * Query parameters: | ||
| * - modulus (optional) – number of buckets; defaults to [[DraftApiProperties.UrlCheckDaysInYear]]. Set to 1 to | ||
| * process every article in a single run. | ||
| * - remainder (optional) – which bucket to process; defaults to the current day-of-year (1-based). | ||
| * | ||
| * Example – run today's scheduled slice: POST /intern/check-urls | ||
| * | ||
| * Example – force-check all articles right now: POST /intern/check-urls?modulus=1&remainder=0 | ||
| */ | ||
| def checkUrls: ServerEndpoint[Any, Eff] = endpoint |
There was a problem hiding this comment.
Denne kommentaren kunne vel like greit vært beskrivelse på endepunktet i form av .description(...) og .example(...)
| quickRequest | ||
| .head(uri"$url") | ||
| .followRedirects(false) | ||
| .readTimeout(scala.concurrent.duration.Duration(10, "seconds")) |
There was a problem hiding this comment.
Snubla over urlen https://deploii.no som bruker laaang tid på å svare på head-kall, men svarer likevel. Så kanskje ha en lengre timeout?
amatho
left a comment
There was a problem hiding this comment.
Jeg syns det blir litt tungvint med disse modulus greiene. Kunne ikke denne jobben bare kjørt på alle artiklene, og heller hatt en form for throttling hvis målet er å unngå å DoS'e lenkene som sjekkes?
|
Det vil fort være en jobb som tar fleire timer kvar gong. |
Hvor mange url'er er det snakk om totalt? Kan ikke forstå at det er tilfellet om vi parallelliserer det? Det bør jo være en rimelig IO heavy jobb som skalerer ganske bra med flere tråder. |
|
Forrige gang eg testa brukte jobben to minutt på ca 130 artikler. Om den skal ta 40000 artikler i en omgang vil det fort ta 40000 sekund, altså 11 timer. |
Vibekoda en parallellisert løsning basert på denne branchen nå (oneshot ingen optimalisering forutenom å be den parallelisere), kjørte gjennom hele test databasen på <30 minutter på min maskin i alle fall. |
Legger til funksjonalitet for å sjekke urler i artikler. Bruker quickRequest for å sende head-spørring og gjør følgende basert på svar:
Har også et endepunkt som kan kalles av en cronjobb for daglig vasking. Endepunktet kan også kalles for å gjøre en full vasking av databasen.