Esri / Esri/arcgis-python-api

Survey.generate_report() — add job timeout and cancel support

Open
#2,531 1 comment 0 reactions 0 assignees View on GitHub
bug
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.**
Image
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.