from typing import Any from fastapi import APIRouter, HTTPException from fastapi.responses import PlainTextResponse from app.infra.cache.redis_client import redis_client from app.services.tjnetwork import ( run_project, run_project_return_dict, run_inp, dump_output, ) from app.algorithms.online_Analysis import ( burst_analysis, valve_close_analysis, flushing_analysis, contaminant_simulation, age_analysis, scheduling_analysis, pressure_regulation, project_management, daily_scheduling_analysis, network_update, pump_failure, pressure_sensor_placement_sensitivity, pressure_sensor_placement_kmeans, ) router = APIRouter() # 必须用这个PlainTextResponse,不然每个key都有引号 @router.get("/runproject/", response_class=PlainTextResponse) async def run_project_endpoint(network: str) -> str: lock_key = "exclusive_api_lock" timeout = 120 # 锁自动过期时间(秒) # 尝试获取锁(NX=True: 不存在时设置,EX=timeout: 过期时间) acquired = redis_client.set(lock_key, "locked", nx=True, ex=timeout) if not acquired: raise HTTPException(status_code=409, detail="is in simulation") else: try: return run_project(network) finally: # 手动释放锁(可选,依赖过期时间自动释放更安全) redis_client.delete(lock_key) # DingZQ, 2025-02-04, 返回dict[str, Any] # output 和 report # output 是 json # report 是 text @router.get("/runprojectreturndict/") async def run_project_return_dict_endpoint(network: str) -> dict[str, Any]: lock_key = "exclusive_api_lock" timeout = 120 # 锁自动过期时间(秒) # 尝试获取锁(NX=True: 不存在时设置,EX=timeout: 过期时间) acquired = redis_client.set(lock_key, "locked", nx=True, ex=timeout) if not acquired: raise HTTPException(status_code=409, detail="is in simulation") else: try: return run_project_return_dict(network) finally: # 手动释放锁(可选,依赖过期时间自动释放更安全) redis_client.delete(lock_key) # put in inp folder, name without extension @router.get("/runinp/") async def run_inp_endpoint(network: str) -> str: return run_inp(network) # path is absolute path @router.get("/dumpoutput/") async def dump_output_endpoint(output: str) -> str: return dump_output(output) # Analysis Endpoints @router.get("/burstanalysis/") async def burst_analysis_endpoint(network: str, pipe_id: str, start_time: str, end_time: str, burst_flow: float): return burst_analysis(network, pipe_id, start_time, end_time, burst_flow) @router.get("/valvecloseanalysis/") async def valve_close_analysis_endpoint(network: str, valve_id: str, start_time: str, end_time: str): return valve_close_analysis(network, valve_id, start_time, end_time) @router.get("/flushinganalysis/") async def flushing_analysis_endpoint(network: str, pipe_id: str, start_time: str, duration: float, flow: float): return flushing_analysis(network, pipe_id, start_time, duration, flow) @router.get("/contaminantsimulation/") async def contaminant_simulation_endpoint(network: str, node_id: str, start_time: str, duration: float, concentration: float): return contaminant_simulation(network, node_id, start_time, duration, concentration) @router.get("/ageanalysis/") async def age_analysis_endpoint(network: str): return age_analysis(network) @router.get("/schedulinganalysis/") async def scheduling_analysis_endpoint(network: str): return scheduling_analysis(network) @router.get("/pressureregulation/") async def pressure_regulation_endpoint(network: str, target_node: str, target_pressure: float): return pressure_regulation(network, target_node, target_pressure) @router.get("/projectmanagement/") async def project_management_endpoint(network: str): return project_management(network) @router.get("/dailyschedulinganalysis/") async def daily_scheduling_analysis_endpoint(network: str): return daily_scheduling_analysis(network) @router.get("/networkupdate/") async def network_update_endpoint(network: str): return network_update(network) @router.get("/pumpfailure/") async def pump_failure_endpoint(network: str, pump_id: str, time: str): return pump_failure(network, pump_id, time) @router.get("/pressuresensorplacementsensitivity/") async def pressure_sensor_placement_sensitivity_endpoint( name: str, scheme_name: str, sensor_number: int, min_diameter: int, username: str ): return pressure_sensor_placement_sensitivity( name, scheme_name, sensor_number, min_diameter, username ) @router.get("/pressuresensorplacementkmeans/") async def pressure_sensor_placement_kmeans_endpoint( name: str, scheme_name: str, sensor_number: int, min_diameter: int, username: str ): return pressure_sensor_placement_kmeans( name, scheme_name, sensor_number, min_diameter, username )