Survey.generate_report() — add job timeout and cancel support
- Dominant language
- Python
- Stars
- 2.2k
- Forks
- 1.2k
- Avg merge
- 2h 40m
- Merged PRs (30d)
- 2
Description
**Is your feature request related to a problem? Please describe.**
In the example above I Had to cancel it manually, after 2h.
`Survey.generate_report()` submits a Feature Report job and polls forever with no timeout (internal loop sleeps while `esriJobExecuting` with no deadline). In batch/ETL PDF generation, a stuck job hangs the process indefinitely. The method also does not return `jobId`, so callers cannot cancel a hung job via the Survey123 cancel endpoint.
We had to bypass `generate_report()` and reimplement submit + poll against the same REST API just to add a timeout and a real cancel.
```python
from arcgis.gis import GIS
from arcgis.apps.survey123 import SurveyManager
gis = GIS(url, username, password)
survey = SurveyManager(gis).get("")
template = gis.content.get("")
# Can hang forever if the job never leaves esriJobExecuting
# (no timeout kwarg; no jobId returned to cancel)
result = survey.generate_report(
report_template=template,
where="OBJECTID=1",
utc_offset="+00:00",
output_format="pdf",
)
```
**Describe the solution you'd like**
Add optional timeout / cancel controls on `Survey.generate_report()` (or `SurveyManager`):
1. `job_timeout` (seconds) — stop polling after N seconds and raise a clear error (e.g. `TimeoutError`).
2. `cancel_on_timeout` — call `POST .../api/featureReport/jobs/{jobId}/cancel` so the remote job does not keep running after the client gives up.
3. Optionally expose `jobId` (or a job handle) so callers can cancel/track jobs themselves.
Example:
```python
result = survey.generate_report(
report_template=template,
where="OBJECTID=1",
output_format="pdf",
job_timeout=90, # NEW
cancel_on_timeout=True, # NEW
)
```
The cancel endpoint already works in practice (`POST .../api/featureReport/jobs/{jobId}/cancel` → `esriJobStatusCancelled`).
**Describe alternatives you've considered**
1. Reimplement submit + poll ourselves (current workaround) — duplicate `_survey.py` logic against `/createReport/submitJob`, `/jobs/{id}/status`, and `/cancel`. Works, but fragile if the private API changes.
2. External process/watchdog timeout — kills the Python process but does not cancel the remote job; wastes credits and leaves orphan jobs.
3. Thread + interrupt — still no access to `jobId`, so cancel is impossible.
**Additional context**
- Affected API: `arcgis.apps.survey123.Survey.generate_report`
- Use case: automated batch PDF Feature Reports in an ETL pipeline (ArcGIS Enterprise / AGOL)
- Related endpoints already used successfully outside the Python API:
- `POST /api/featureReport/createReport/submitJob`
- `GET /api/featureReport/jobs/{jobId}/status`
- `POST /api/featureReport/jobs/{jobId}/cancel`
Contributor guide
Research direction
Start in _survey.py at Survey.generate_report(), then trace the submit, status-polling, and cancel endpoints named in the issue. Verify finite job_timeout handling, TimeoutError, optional cancellation, and jobId or handle exposure; done means a stuck job stops polling and the remote job is cancelled when requested.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 56/100