Skip to content

Give every check an overall time limit and run one check at a time per page - #26

Merged
fabianekc merged 1 commit into
mainfrom
check-deadline
Oct 19, 2026
Merged

fabianekc merged 1 commit into
mainfrom
check-deadline

Conversation

@fabianekc

Copy link
Copy Markdown
Member

Summary

A check could take far longer than the start page waits for it: against a passport host that accepts connections but never answers, a check ran for about 100 s, and it kept running on the server after the page had given up. While three such checks ran, the service answered nothing else.

  • Overall time limit: every check of the API (GET and POST) ends within CHECK_DEADLINE seconds, 35 by default. The limits of single requests stay (name lookup 5 s, connection 10 s, answer 20 s per redirect, links 10 s, SOyA web-cli 5 s and 30 s, didlint 10 s per request and 20 s per check), but each request waits at most the time left, connection and answer together.
  • Partial result: once the time is up, no further request is sent. Criteria evaluated so far keep their results; criteria cut off are skipped with reason_code not_evaluated and the reason "the time limit of 35 s for this check was reached". A timeout counts against the host only if its own limits were not shortened by the time limit. The result has a new field timeLimit (seconds, reached) and a notice when the limit was reached.
  • Nothing left behind: the parallel link requests are all joined before the check ends, and every request closes its connection when it gives up.
  • One check per page: the start page waits CHECK_DEADLINE plus 5 s (40 s by default). While a check runs, the form, the example links and "Try again" send no further request.

Changes

  • app/services/check_deadline.rb (new): the time limit of one check; splits the time left into connect and read limits per request.
  • app/services/http_resolver.rb, passport_fetcher.rb, links_check.rb, soya_web_cli.rb, didlint.rb: limits cut to the time left; name lookup with an overall limit; link requests joined.
  • app/services/passport_linter.rb, app/controllers/api/v1/validations_controller.rb: one time limit per request, partial result, timeLimit, notice.
  • app/javascript/check_client.js, app/views/home/show.html.erb: one check at a time per page.
  • config/initializers/dpplint.rb: CHECK_DEADLINE; CHECK_TIMEOUT follows it.
  • swagger/v1/swagger.yaml, README.md: timeLimit, the limits.
  • Tests: test/services/check_deadline_test.rb, test/integration/check_time_limit_test.rb, test/support_slow_server.rb (new), JavaScript tests for one check at a time, adapted page and resolver tests.

Tests

  • Full suite in the image: 241 runs, 0 failures, 0 errors.
  • With a time limit of 1.5 s: a hanging passport host, slow redirects (0.4 s per hop), 20 slow links, a hanging SOyA web-cli and a hanging didlint each end within 1.3 s, and no request is left open. Without the change, the same cases wait 20 s, 2.1 s (five hops), 10.3 s, 30 s and 10 s.
  • Partial result: a passed criterion stays, two cut-off criteria are not_evaluated with the reason, a criterion without network access stays not_applicable; timeLimit.reached is true.
  • Through the API, against a hanging passport host with a time limit of 3 s: answer after 2.9 s. Without the change: 100.5 s.
  • With the default limits, three checks at the same time against a hanging host end after 34.7 s each (100.4 s without the change).
  • Two starts from the same page in a browser: one API request (three without the change).

…r page

A check of the API now ends within CHECK_DEADLINE seconds (default 35). The
limits of single requests stay (name lookup, connection and answer per
redirect, links, SOyA web-cli, didlint), but each request waits at most the
time left. Once the time is up, no further request is sent: the criteria
evaluated so far keep their results, the others are skipped as not_evaluated
with the reason, and timeLimit and notices in the result say that the limit
was reached. Link requests are all joined before the check ends, so nothing
of a check keeps running after its answer.

The start page waits CHECK_DEADLINE plus 5 s (40 s by default) and runs one
check at a time: while a check runs, the form, the examples and "Try again"
send no further request.

Tests cover a hanging passport host, slow redirects, many slow links, a slow
SOyA web-cli and didlint, a partial result at the time limit, a JWS request
cut off by it and two starts from the same page.
@fabianekc
fabianekc merged commit 86ee531 into main Oct 19, 2026
2 checks passed
@fabianekc
fabianekc deleted the check-deadline branch October 19, 2026 20:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant