SWMM Feature Function App — Developer Guide
This document summarizes how swmm-feature-function is built, run, tested, and published. It is written for engineers who want to reproduce a similar Azure Functions (Python v2 programming model) app using the same toolchain and patterns.
Primary reference we used when scaffolding and day-to-day development: Develop Azure Functions using Visual Studio Code (Python v2 model, local settings, Core Tools, deploy from VS Code).
For Azure resource names, connection strings, and detailed environment variable tables, see DEPLOYMENT.md and Feature_Function_Readme.md in this folder.
Documentation mirror: These Markdown files are collected in
projects/internal/HydroTrek/02_SSC/SWMM/swmm-feature-function/(same folder as this guide). The authoritative source tree is the swmm-feature-function repository; keep copies in sync when those files change.
What this app does (high level)
- Input: SWMM
.inpfiles (and.slpkscene packages) in Azure Blob Storage, plus project state in Azure Table Storage. - Processing: Parse INP, build GeoJSON (including optional hybrid INP + engine attributes), publish layers to ArcGIS Online, and update project / feature metadata tables.
- Interface: HTTP endpoints in
function_app.py(health, publish, delete). An upstream API typically uploads blobs, then callspublish-project-layersorpublish-scene-layerswith JSON (seefunction_app.pydocstrings).
Note: Some older docs in this repo describe a blob-triggered function as the primary path. The current Python entrypoint exposes only HTTP routes (
@app.route). Treatfunction_app.pyas the source of truth for triggers; blob triggers would be a separate addition if you need them.
Technology stack
| Area | Choice |
|---|---|
| Platform | Azure Functions runtime v4, Python worker |
| Programming model | Python v2 — single function_app.py, app = func.FunctionApp(), decorators (@app.route) |
| HTTP | azure.functions (HttpRequest / HttpResponse) |
| Azure data plane | azure-storage-blob, azure-storage-queue, azure-data-tables |
| GIS | arcgis Python API |
| Geodesy / CRS | pyproj |
| SWMM / hybrid attributes | Bundled pyswmm-style code under publisher/ + swmm-toolkit (see requirements.txt) |
| Observability | azure-monitor-opentelemetry (see comment in requirements.txt) |
| Binding extensions | Extension bundle in host.json (no manual per-binding NuGet-style install for Python) |
| Local tooling | Azure Functions Core Tools (func), VS Code + Azure Functions extension |
Prerequisites
Install and configure the following before cloning and running:
- Python — version aligned with your Function App in Azure (this project targets Python 3.11 in deployment docs; use the same locally).
- Visual Studio Code with extensions recommended in
.vscode/extensions.json: - Azure Functions Core Tools — install or upgrade from VS Code: Azure Functions: Install or Update Azure Functions Core Tools, or follow Run Azure Functions locally.
- Azure subscription (for publish) and an Azure Storage account connection string for
AzureWebJobsStorage— required for the Functions host for non-HTTP scenarios and for storage-backed bindings; set inlocal.settings.jsonwhen running locally (see Microsoft doc: Configure the project to run locally).
Optional but typical for full integration tests:
- ArcGIS Online API key (
ARCGIS_API_KEY). - Storage account name + SAS or connection string for app blobs and tables (details in DEPLOYMENT.md).
How we created / scaffolded the project
We followed the VS Code flow described in Microsoft’s article: Azure Functions: Create New Project..., chose Python, the Python v2 programming model, and added HTTP-triggered functions as needed. That produces (or you maintain):
function_app.py— all function definitions and handlers.host.json— host-wide settings (logging, extension bundle, retry, extension-specific options).local.settings.json— local-only secrets andValuesmirrored from Azure app settings (exclude from git; use your own copy).requirements.txt— Python dependencies deployed with the app.
The repo also includes .vscode/tasks.json and .vscode/launch.json so F5 can start the host and attach the debugger (see below).
Design decisions
- Python v2 programming model — One
FunctionAppinstance and decorators keep definitions co-located and avoid a forest offunction.jsonfolders. This matches current Azure guidance for new Python Functions (same article as above). - HTTP-only triggers in code — Publish and delete are explicit REST-style operations invoked by the SWMM API after uploads. That keeps orchestration visible in application logs and allows idempotency and validation in one place.
- Function-level auth for publish/delete — Endpoints use
auth_level=FUNCTIONexcept/api/health, which isANONYMOUSfor cheap probes. Callers pass the function key (querycode=or header per Azure conventions) when testing locally or in the cloud. - Blob + Table via SDK — The app uses storage clients (connection string or account + SAS) to download INP/SLPK and read/write status tables, rather than relying on output bindings for the core workflow. That keeps complex branching and error handling in standard Python.
- Extension bundle
[4.*, 5.0.0)— Declared inhost.jsonso queue/timer/blob extensions stay aligned with the host without pinning many packages in Python (see extension bundles in the Microsoft doc). - Retries — Global retry policy in
host.json(exponentialBackoff, bounded attempts) for transient host-level failures; business logic usesMAX_ATTEMPTSand table-backed status (see Feature_Function_Readme.md). - Hybrid GeoJSON — Optional INP + engine-backed attributes behind
USE_HYBRID_GEOJSON(default on) with INP-only fallback; schema centralized inpublisher/geojson_schema.pyand builders inpublisher/geojson_builders.py. - Attribute maps in Table Storage — Field names for ArcGIS are driven by rows in the AttributeMap table (supports a static-partition layout and a legacy layout); see
function_app._load_attribute_map_for_partitionandscripts/upload_attribute_map_fieldmaps.py.
Run locally
From the repository root (swmm-feature-function/):
Create or copy
local.settings.json(not committed with secrets — useValuesfrom DEPLOYMENT.md as a checklist).Install dependencies (the VS Code task uses the Functions Python venv):
cd c:\Git\gqc\hydrotrek-ssc-suite-fresh\swmm-feature-function
python -m pip install -r requirements.txtStart the Functions host:
func startDefault local base URL is
http://localhost:7071. Routes are exposed under/api/<route>(e.g.http://localhost:7071/api/health).
VS Code: Run the “Attach to Python Functions” configuration — it runs the func: host start task (which runs pip install then host start) and attaches debugpy on port 9091. See .vscode/launch.json and .vscode/tasks.json.
Test locally
Automated tests (publisher / GeoJSON)
From the repo root:
python -m pip install pytest
python -m pytest tests/ -v
Focused examples:
python -m pytest tests/test_geojson_hybrid.py -v
Details and optional fixtures: Testing.md.
Exercise HTTP endpoints (full stack)
With func start running and local.settings.json populated:
curl http://localhost:7071/api/health
Publish (replace YOUR_FUNCTION_KEY with the key from Core Tools output or Azure portal):
curl -X POST "http://localhost:7071/api/publish-project-layers?code=YOUR_FUNCTION_KEY" `
-H "Content-Type: application/json" `
-d "{\"projectId\": \"YourProjectId\"}"
Optional body fields are documented in function_app.py (e.g. blobPath, projectName, epsg).
Publish from a local INP without Azure (ArcGIS only)
See Testing.md — tests/test_publish_features.py with --inp and ARCGIS_API_KEY.
Publish to Azure
Deployment is manual in our workflow (CI to Flex Consumption can be finicky — see notes in DEPLOYMENT.md).
Option A — Azure Functions Core Tools:
cd c:\Git\gqc\hydrotrek-ssc-suite-fresh\swmm-feature-function
func azure functionapp publish YOUR_FUNCTION_APP_NAME
Option B — Visual Studio Code: Command Palette → Azure Functions: Deploy to Function App (see Deploy project files).
After deploy:
- Upload application settings if needed: Azure Functions: Upload Local Setting or the portal —
local.settings.jsonValuesshould mirror the Function App’s configuration (never commit secrets). - Smoke test:
curl https://YOUR_FUNCTION_APP_NAME.azurewebsites.net/api/health
Full environment variable list and Azure CLI examples: DEPLOYMENT.md.
File map (quick reference)
| File / folder | Role |
|---|---|
function_app.py | HTTP functions and request handling |
host.json | Host logging, extension bundle, retry and queue extension knobs |
requirements.txt | Deployed Python dependencies |
publisher/ | INP parsing, GeoJSON build, ArcGIS publish, storage helpers |
tests/ | Pytest suites and manual test scripts |
.vscode/ | Tasks and debugger attach for local Functions host |