Skip to content

UWS conformance: job deletion, 404 for unknown jobs, executionDuration, consistent job values - #33

Open
bjfultn wants to merge 1 commit into
developfrom
fix/uws-conformance
Open

bjfultn wants to merge 1 commit into
developfrom
fix/uws-conformance

Conversation

@bjfultn

@bjfultn bjfultn commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator

Why

The Euro-VO registry runs taplint, the IVOA's TAP validator, against registered services. It reports four async (UWS) errors for an archive running nexsciTAP:

E-UWS-DENO Deleted job gives HTTP response 200 not 404
E-UWS-HTDE Failed to perform HTTP DELETE ... HTTP response code: 500
E-UWS-JDED Execution duration mismatch between job info and /executionduration URL (null != 0)
E-UWS-JDDE Destruction time mismatch between job info and /destruction URL ( != None)

All four reproduce on develop.

Changes

taplint Cause Fix
DENO Deletion was never implemented: POST ACTION=DELETE returned the job document and the job remained POST ACTION=DELETE and HTTP DELETE stop the job if it is EXECUTING (as PHASE=ABORT does), remove its workspace, and answer 303 to the job list. The job is then 404.
HTDE cgi.FieldStorage raises not indexable on a request with no form fields, so every HTTP DELETE failed at startup with 500 Form fields are read only when there are some
JDED The job document wrote <uws:executionduration>; UWS names it executionDuration, so taplint found no element (null) Written as executionDuration. Reading still accepts the lowercase form, for jobs written by earlier releases (jobs live 4 days).
JDDE An unset value is an empty element in the job document, but /destruction printed Python's None Unset or nil values read back as empty text

Also:

  • Unknown jobs return 404, not 500.
  • Job IDs are validated. They must match the workspace-name pattern (tap_ followed by letters, digits or _). Before this, an ID such as .. resolved to the work directory itself, which matters now that deletion removes whatever the ID names. The tests send these paths unnormalized, since requests would strip . and .. first.
  • GET on the job list no longer creates a job. It created an empty job before, and clients follow the delete redirect with a GET there, so each delete would have left a junk job. It now returns an empty <uws:jobs>. Jobs carry no owner, so the list shows none of them rather than everyone's.
  • Job URLs use one slash. HTTP_URL and CGI_PGM are joined with one / (CGI_PGM=/TAP used to give host//TAP/async/...). Compat mode keeps NEA's current form.
  • The test server accepts DELETE (tests/conftest.py).

Behavior changes for existing deployments

  • Default mode (NEID, KOA): executionDuration casing, the single-slash job URLs, and the new delete, 404 and job-list behaviors.
  • Compat mode (NEA): delete, the 404s, the job list and the empty unset values only. All 18 NEA smoke responses stay byte-identical to NEA production.
  • MIGRATING.md is updated. The executionDuration part of nea-uws is retired, as its release plan anticipated.

Verification

  • tests/test_uws_conformance.py mirrors taplint's four checks and adds job-ID validation, the job list, deleting a completed job, and delete in compat mode. All of it failed before the change (17 failures) and passes now.
  • Full suite: 129 passed, 2 skipped. ruff clean.
  • Containerized replica with NEA's production data:

taplint itself wasn't run against this branch. The tests reproduce what it reported.

🤖 Generated with Claude Code

taplint (E-UWS-DENO, -HTDE, -JDED, -JDDE) reports four async problems:

- Deleting a job did nothing: POST ACTION=DELETE returned the job, and
  HTTP DELETE was a 500 because FieldStorage raises 'not indexable' on
  a request without form fields.  Both now stop a running job, remove
  its workspace and answer 303 to the job list; the job is then 404.
- An unknown job id was a 500; it is 404.  Job ids must match the
  workspace name pattern (tap_...), so no id reaches outside
  <workdir>/TAP.
- The job document wrote <uws:executionduration>; UWS names it
  executionDuration.  Reading accepts both, for jobs written earlier.
- An unset value read back as the text 'None' (/destruction before a job
  runs) while the job document had it empty; both are now empty.

GET on the job list returned a new job; it now returns an empty
<uws:jobs>, since clients follow the deletion redirect there.  Job URLs
join HTTP_URL and CGI_PGM with one slash (NEA keeps its form).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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