Skip to main content

SWMM Inputs to Runs Relationship Implementation Plan

Executive Summary

✅ COMPLETED - This document outlines the successful implementation of modifying the SWMM projects' data storage architecture from a 1:many relationship between Inputs and Runs tables to a 1:1 relationship. The implementation ensures only one run exists per input/scenario, with automatic cleanup handled by the worker engine.

✅ Implemented Architecture

New Data Flow

  1. Input Creation: API creates entries in Inputs table with RunFlag = true
  2. Worker Processing: Worker function queries for RunFlag = true entries
  3. Automatic Cleanup: Worker cleans up existing run data before processing
  4. Run Creation: Worker creates/updates single run entry with fixed RowKey "current"
  5. Flag Reset: Worker sets RunFlag = false to prevent re-processing
  6. Result Storage: Results stored in multiple output tables (cleaned up before new run)

Implemented Key Components

Table Entities

  • SwmmInputEntity: Contains scenario parameters and RunFlag
  • SwmmRunEntity: Contains run metadata, status, and results

New PartitionKey/RowKey Strategy

  • Inputs Table:
    • PartitionKey: User/Client identifier
    • RowKey: Scenario identifier
  • Runs Table:
    • PartitionKey: {inputPartitionKey}_{inputRowKey} (scenario-specific)
    • RowKey: "current" (fixed for 1:1 relationship)

Output Tables

  • SystemOutput: System-level results (automatically cleaned up)
  • LinkOutput: Link-specific time series data (automatically cleaned up)
  • NodeOutput: Node-specific time series data (automatically cleaned up)
  • SubcatchOutput: Subcatchment-specific time series data (automatically cleaned up)

✅ Implemented Changes

1. Data Layer Implementation

1.1 Runs Table Operations ✅

Implemented: Fixed RowKey for 1:1 relationship with automatic cleanup

// Implemented: Fixed RowKey for 1:1 relationship
string runRowKey = "current"; // Fixed RowKey for 1:1 relationship
SwmmRunEntity currentRun = new SwmmRunEntity()
{
PartitionKey = runPartitionKey, // Same as input
RowKey = runRowKey, // Fixed value
// ... other properties
};

// Clean up existing data before creating new run
await CleanupExistingRunDataAsync(runPartitionKey, input.RowKey);

// Use upsert logic (existing AddOrUpdateRunsEntity method handles this)
currentRun = AddOrUpdateRunsEntity(currentRun);

1.2 Output Tables Cleanup Strategy ✅

Implemented: Automatic cleanup before new runs

  • ✅ Clean up existing output data for the scenario before new run
  • ✅ Clean up SystemOutput, LinkOutput, NodeOutput, SubcatchOutput tables
  • ✅ Clean up associated blob storage
  • ✅ Batch processing for efficient cleanup
  • ✅ Error handling to prevent run failures

2. API Layer Implementation ✅

2.1 New Input Files Management Controller ✅

Created: swmm-api-aspnet/SwmmApiAspnet/Controllers/InputFilesController.cs

Features:

  • ✅ List available input files from blob storage
  • ✅ Upload new input files with validation
  • ✅ Download input files
  • ✅ Delete input files
  • ✅ File metadata management
  • ✅ Proper dependency injection for BlobServiceClient

2.2 Enhanced RunManagementController ✅

Updated: swmm-api-aspnet/SwmmApiAspnet/Controllers/RunManagementController.cs

New Endpoints:

  • GET /api/runmanagement/{scenarioId}/{scenarioName}/current - Get current run (1:1)
  • POST /api/runmanagement/{scenarioId}/{scenarioName}/trigger-run - Trigger new run
  • GET /api/runmanagement/{scenarioId}/{scenarioName}/latest-completed - Get completed run
  • ✅ Legacy endpoints preserved for backward compatibility

Key Improvements:

  • ✅ Proper dependency injection for Azure services
  • ✅ Clean separation of concerns (API triggers, Worker processes)
  • ✅ No duplication of cleanup logic

3. Worker Function Implementation ✅

3.1 Enhanced Worker Function ✅

Updated: swmm-worker-function/SwmmWorkerFunction8/SwmmWorkerFunction8.cs

Implemented Features:

  • ✅ Fixed RowKey "current" for 1:1 relationship
  • ✅ Automatic cleanup before new runs
  • ✅ Batch processing for efficient cleanup
  • ✅ Comprehensive error handling
  • ✅ Blob storage cleanup with correct container naming

3.2 Cleanup Implementation ✅

// Implemented cleanup functions
private async Task CleanupExistingRunDataAsync(string partitionKey, string scenarioId)
{
// Clean up output tables in parallel
var cleanupTasks = new List<Task>
{
CleanupOutputTableAsync(SysOutputTableName, partitionKey, scenarioId),
CleanupOutputTableAsync(LinkOutputTableName, partitionKey, scenarioId),
CleanupOutputTableAsync(NodeOutputTableName, partitionKey, scenarioId),
CleanupOutputTableAsync(SubcatchOutputTableName, partitionKey, scenarioId),
CleanupBlobStorageAsync(partitionKey, scenarioId)
};

await Task.WhenAll(cleanupTasks);
}

✅ Implementation Phases - COMPLETED

Phase 1: Data Layer Foundation ✅

  1. Update Entity Operations: Modified worker to use fixed RowKey "current"
  2. Implement Cleanup Logic: Added comprehensive cleanup functions for output tables and blob storage
  3. Update Worker Function: Modified main worker logic for 1:1 relationship
  4. Testing: Validated in development environment

Phase 2: API Layer Updates ✅

  1. New Controller: Created InputFilesController for file management
  2. Enhanced Controllers: Updated RunManagementController with new endpoints
  3. Dependency Injection: Proper Azure service registration and injection
  4. Backward Compatibility: Legacy endpoints preserved

Phase 3: Data MigrationNOT NEEDED

Reason: The automatic cleanup in the worker function handles existing data naturally. When a scenario with multiple existing runs is triggered, the worker will:

  1. Clean up all existing output data
  2. Create/update the single run with RowKey "current"
  3. No manual migration required

Phase 4: Monitoring and Optimization ✅

  1. Performance Optimizations: Proper DI, connection pooling, batch operations
  2. Error Handling: Comprehensive error handling and logging
  3. Documentation: Updated implementation plan and API documentation
  4. Clean Architecture: Proper separation of concerns

✅ Technical Implementation Details

1. Concurrency Handling ✅

  • ETag Management: Proper ETag handling in AddOrUpdateRunsEntity method
  • Error Handling: Graceful handling of concurrent updates
  • Thread Safety: Azure SDK handles concurrency automatically

2. Performance Optimizations ✅

  • Batch Operations: Batch processing for cleanup operations (100 entity limit)
  • Async Operations: All operations properly async
  • Connection Pooling: Dependency injection for Azure services
  • Parallel Processing: Cleanup tasks run in parallel

3. Error Handling ✅

  • Partial Failures: Cleanup failures don't prevent run execution
  • Comprehensive Logging: Detailed logging for troubleshooting
  • Graceful Degradation: System continues to function if cleanup fails

4. Blob Storage Implementation ✅

  • Blob Cleanup: Automatic cleanup of associated blob storage
  • Correct Naming: Proper client-specific container naming ({clientKey}-swmm-output)
  • File Management: New InputFilesController for comprehensive file management

✅ Risk Assessment - MITIGATED

High RiskRESOLVED

  • Data Loss: Comprehensive testing and error handling implemented
  • Concurrency Issues: Proper ETag management and Azure SDK thread safety
  • Migration Failures: No migration needed - automatic cleanup handles existing data

Medium RiskRESOLVED

  • Performance Impact: Optimized with batch operations and parallel processing
  • API Breaking Changes: Backward compatibility preserved with legacy endpoints
  • Storage Costs: Reduced through automatic cleanup of duplicate data

Low Risk - ACCEPTABLE

  • Configuration Changes: Minimal - just DI registration
  • Documentation Updates: Completed

✅ Success Criteria - ACHIEVED

  1. Functional: 1:1 relationship properly implemented
  2. Performance: Optimized with proper DI and batch operations
  3. Data Integrity: Automatic cleanup with error handling
  4. API Compatibility: Legacy endpoints preserved, new endpoints added
  5. Storage Efficiency: Automatic cleanup reduces duplicate data

✅ Implementation Timeline - COMPLETED

  • Phase 1: Data Layer Foundation (Completed)
  • Phase 2: API Layer Updates (Completed)
  • Phase 3: Data Migration (Not Needed)
  • Phase 4: Monitoring and Optimization (Completed)
  • Total: COMPLETED SUCCESSFULLY

✅ Key Achievements

  1. 1:1 Relationship: Successfully implemented fixed RowKey "current"
  2. Automatic Cleanup: Worker handles cleanup before new runs
  3. Input File Management: New controller for comprehensive file operations
  4. Clean Architecture: Proper separation of concerns
  5. Performance: Optimized with proper DI and batch operations
  6. Backward Compatibility: Legacy endpoints preserved