Skip to main content

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 .inp files (and .slpk scene 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 calls publish-project-layers or publish-scene-layers with JSON (see function_app.py docstrings).

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). Treat function_app.py as the source of truth for triggers; blob triggers would be a separate addition if you need them.


Technology stack

AreaChoice
PlatformAzure Functions runtime v4, Python worker
Programming modelPython v2 — single function_app.py, app = func.FunctionApp(), decorators (@app.route)
HTTPazure.functions (HttpRequest / HttpResponse)
Azure data planeazure-storage-blob, azure-storage-queue, azure-data-tables
GISarcgis Python API
Geodesy / CRSpyproj
SWMM / hybrid attributesBundled pyswmm-style code under publisher/ + swmm-toolkit (see requirements.txt)
Observabilityazure-monitor-opentelemetry (see comment in requirements.txt)
Binding extensionsExtension bundle in host.json (no manual per-binding NuGet-style install for Python)
Local toolingAzure Functions Core Tools (func), VS Code + Azure Functions extension

Prerequisites

Install and configure the following before cloning and running:

  1. Python — version aligned with your Function App in Azure (this project targets Python 3.11 in deployment docs; use the same locally).
  2. Visual Studio Code with extensions recommended in .vscode/extensions.json:
  3. 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.
  4. 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 in local.settings.json when 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.jsonlocal-only secrets and Values mirrored 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

  1. Python v2 programming model — One FunctionApp instance and decorators keep definitions co-located and avoid a forest of function.json folders. This matches current Azure guidance for new Python Functions (same article as above).
  2. 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.
  3. Function-level auth for publish/delete — Endpoints use auth_level=FUNCTION except /api/health, which is ANONYMOUS for cheap probes. Callers pass the function key (query code= or header per Azure conventions) when testing locally or in the cloud.
  4. 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.
  5. Extension bundle [4.*, 5.0.0) — Declared in host.json so queue/timer/blob extensions stay aligned with the host without pinning many packages in Python (see extension bundles in the Microsoft doc).
  6. Retries — Global retry policy in host.json (exponentialBackoff, bounded attempts) for transient host-level failures; business logic uses MAX_ATTEMPTS and table-backed status (see Feature_Function_Readme.md).
  7. Hybrid GeoJSON — Optional INP + engine-backed attributes behind USE_HYBRID_GEOJSON (default on) with INP-only fallback; schema centralized in publisher/geojson_schema.py and builders in publisher/geojson_builders.py.
  8. 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_partition and scripts/upload_attribute_map_fieldmaps.py.

Run locally

From the repository root (swmm-feature-function/):

  1. Create or copy local.settings.json (not committed with secrets — use Values from DEPLOYMENT.md as a checklist).

  2. 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.txt
  3. Start the Functions host:

    func start

    Default 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.mdtests/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.json Values should 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 / folderRole
function_app.pyHTTP functions and request handling
host.jsonHost logging, extension bundle, retry and queue extension knobs
requirements.txtDeployed 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