refactor(storage): route project DSNs and remove legacy backends
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
from fastapi import APIRouter, Query
|
||||
from app.infra.cache.redis_client import redis_client
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.delete("/redis-keys/detail", summary="清除单个缓存键", description="根据键名清除单个Redis缓存")
|
||||
async def fastapi_clear_redis_key(key: str = Query(..., description="缓存键名")):
|
||||
"""
|
||||
清除单个缓存键
|
||||
|
||||
根据指定的键名删除Redis中对应的缓存
|
||||
"""
|
||||
redis_client.delete(key)
|
||||
return True
|
||||
|
||||
|
||||
@router.delete("/redis-keys", summary="清除匹配的缓存键", description="根据模式清除匹配的Redis缓存键")
|
||||
async def fastapi_clear_redis_keys(keys: str = Query(..., description="缓存键模式(支持通配符)")):
|
||||
"""
|
||||
清除匹配的缓存键
|
||||
|
||||
根据指定的模式删除Redis中所有匹配的缓存键
|
||||
"""
|
||||
# delete keys contains the key
|
||||
matched_keys = redis_client.keys(f"*{keys}*")
|
||||
if matched_keys:
|
||||
redis_client.delete(*matched_keys)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@router.delete("/all-redis", summary="清除所有缓存", description="清空整个Redis数据库的所有缓存")
|
||||
async def fastapi_clear_all_redis():
|
||||
"""
|
||||
清除所有缓存
|
||||
|
||||
清空Redis数据库中的所有缓存键值对
|
||||
"""
|
||||
redis_client.flushdb()
|
||||
return True
|
||||
|
||||
|
||||
@router.get("/redis", summary="查询缓存键列表", description="获取Redis中所有的缓存键")
|
||||
async def fastapi_query_redis():
|
||||
"""
|
||||
查询缓存键列表
|
||||
|
||||
获取Redis数据库中所有的缓存键列表
|
||||
"""
|
||||
# Helper to decode bytes to str for JSON response if needed,
|
||||
# but original just returned keys (which might be bytes in redis-py unless decode_responses=True)
|
||||
# create_redis_client usually sets decode_responses=False by default.
|
||||
# We will assume user handles bytes or we should decode.
|
||||
# Original just returned redis_client.keys("*")
|
||||
keys = redis_client.keys("*")
|
||||
# Clean output for API
|
||||
return [k.decode('utf-8') if isinstance(k, bytes) else k for k in keys]
|
||||
@@ -17,8 +17,13 @@ from app.auth.metadata_dependencies import (
|
||||
get_current_metadata_admin,
|
||||
get_metadata_repository,
|
||||
)
|
||||
from app.auth.project_dependencies import (
|
||||
ProjectContext,
|
||||
resolve_project_business_routing,
|
||||
)
|
||||
from app.core.audit import AuditAction, log_audit_event
|
||||
from app.infra.db.metadb.repositories.metadata_repository import MetadataRepository
|
||||
from app.infra.db.project_routing import activate_project_routing
|
||||
from app.services.network_import import network_update
|
||||
from app.services.tjnetwork import run_inp
|
||||
|
||||
@@ -118,21 +123,21 @@ async def _run_uploaded_inp(content: bytes) -> str:
|
||||
return run_inp(model_name)
|
||||
|
||||
|
||||
async def _update_from_inp(content: bytes) -> None:
|
||||
async def _update_from_inp(content: bytes, project_code: str) -> None:
|
||||
temp_path: Path | None = None
|
||||
try:
|
||||
with NamedTemporaryFile(suffix=".inp", delete=False) as temp_file:
|
||||
temp_file.write(content)
|
||||
temp_path = Path(temp_file.name)
|
||||
network_update(str(temp_path))
|
||||
network_update(str(temp_path), project_code)
|
||||
finally:
|
||||
if temp_path is not None:
|
||||
temp_path.unlink(missing_ok=True)
|
||||
|
||||
|
||||
async def _apply_model_update(content: bytes) -> None:
|
||||
async def _apply_model_update(content: bytes, project_code: str) -> None:
|
||||
try:
|
||||
await _update_from_inp(content)
|
||||
await _update_from_inp(content, project_code)
|
||||
except Exception as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
@@ -177,7 +182,19 @@ async def update_project_model(
|
||||
) -> dict:
|
||||
project = await _get_active_project(project_id, metadata_repo)
|
||||
content, filename = await _read_upload(file)
|
||||
await _apply_model_update(content)
|
||||
routing = await resolve_project_business_routing(
|
||||
ProjectContext(
|
||||
project_id=project.id,
|
||||
project_code=project.code,
|
||||
user_id=current_user.id,
|
||||
project_role="owner",
|
||||
system_role=current_user.role,
|
||||
is_superuser=current_user.is_superuser,
|
||||
),
|
||||
metadata_repo,
|
||||
)
|
||||
with activate_project_routing(routing):
|
||||
await _apply_model_update(content, project.code)
|
||||
await _audit_model_change(
|
||||
request=request,
|
||||
current_user=current_user,
|
||||
|
||||
@@ -333,7 +333,6 @@ async def fastapi_get_all_junction_properties(
|
||||
list: 包含所有节点属性的列表
|
||||
"""
|
||||
# 缓存查询结果提高性能
|
||||
# global redis_client # Redis logic removed for clean split, can be re-added if needed or imported
|
||||
results = get_all_junctions(network)
|
||||
return results
|
||||
|
||||
|
||||
@@ -385,7 +385,6 @@ async def fastapi_get_all_pipe_properties(
|
||||
包含所有管道属性的字典列表
|
||||
"""
|
||||
# 缓存查询结果提高性能
|
||||
# global redis_client
|
||||
results = get_all_pipes(network)
|
||||
return results
|
||||
|
||||
|
||||
@@ -177,7 +177,6 @@ async def fastapi_get_all_pump_properties(
|
||||
包含所有水泵属性的字典列表
|
||||
"""
|
||||
# 缓存查询结果提高性能
|
||||
# global redis_client
|
||||
results = get_all_pumps(network)
|
||||
return results
|
||||
|
||||
|
||||
@@ -540,7 +540,6 @@ async def fastapi_get_all_tank_properties(
|
||||
包含所有水箱属性的字典列表
|
||||
"""
|
||||
# 缓存查询结果提高性能
|
||||
# global redis_client
|
||||
results = get_all_tanks(network)
|
||||
return results
|
||||
|
||||
|
||||
@@ -307,7 +307,6 @@ async def fastapi_get_all_valve_properties(
|
||||
返回指定水网中所有阀门的完整属性列表。
|
||||
"""
|
||||
# 缓存查询结果提高性能
|
||||
# global redis_client
|
||||
results = get_all_valves(network)
|
||||
return results
|
||||
|
||||
|
||||
@@ -17,7 +17,16 @@ from app.api.problem_details import ProblemDetails
|
||||
from app.api.pagination import PaginatedList
|
||||
from app.api.v1.router import api_router as handler_api_router
|
||||
from app.auth.metadata_dependencies import get_current_metadata_user
|
||||
from app.auth.project_dependencies import ProjectContext, get_project_context
|
||||
from app.auth.project_dependencies import (
|
||||
ProjectContext,
|
||||
get_project_business_routing,
|
||||
get_project_context,
|
||||
get_project_simulation_routing,
|
||||
)
|
||||
from app.infra.db.project_routing import (
|
||||
ActiveProjectRouting,
|
||||
activate_project_routing,
|
||||
)
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
@@ -44,6 +53,13 @@ _PUBLIC_PARAMETER_RENAMES = {
|
||||
}
|
||||
_MODEL_NAME_IS_NETWORK = {"RunSimulationManuallyByDate", "PressureSensorPlacement"}
|
||||
_MODEL_USERNAME_FROM_AUTH = {"PressureSensorPlacement"}
|
||||
_TIMESCALE_ROUTED_ENDPOINT_MODULES = {
|
||||
"app.api.v1.endpoints.burst_detection",
|
||||
"app.api.v1.endpoints.burst_location",
|
||||
"app.api.v1.endpoints.leakage",
|
||||
"app.api.v1.endpoints.simulation",
|
||||
}
|
||||
_TIMESCALE_ROUTED_ENDPOINT_NAMES = {"open_project_endpoint"}
|
||||
|
||||
|
||||
def _clean_name(name: str) -> str:
|
||||
@@ -128,10 +144,14 @@ def _with_header_project_context(endpoint, route_name: str):
|
||||
None,
|
||||
)
|
||||
injected_context_name = existing_context_parameter or "_rest_project_context"
|
||||
injected_routing_name = "_rest_project_routing"
|
||||
injected_user_name = "_rest_current_user"
|
||||
|
||||
@wraps(endpoint)
|
||||
async def wrapper(*args, **kwargs):
|
||||
project_routing = kwargs.pop(injected_routing_name, None)
|
||||
if not isinstance(project_routing, ActiveProjectRouting):
|
||||
raise RuntimeError("REST project database routing was not resolved")
|
||||
project_context = kwargs.get(injected_context_name)
|
||||
if not isinstance(project_context, ProjectContext):
|
||||
raise RuntimeError("REST project context was not resolved")
|
||||
@@ -162,10 +182,11 @@ def _with_header_project_context(endpoint, route_name: str):
|
||||
kwargs[parameter_name] = original_model.model_validate(data)
|
||||
if model_has_username:
|
||||
kwargs.pop(injected_user_name, None)
|
||||
result = endpoint(*args, **kwargs)
|
||||
if inspect.isawaitable(result):
|
||||
return await result
|
||||
return result
|
||||
with activate_project_routing(project_routing):
|
||||
result = endpoint(*args, **kwargs)
|
||||
if inspect.isawaitable(result):
|
||||
return await result
|
||||
return result
|
||||
|
||||
parameters = []
|
||||
for name, parameter in signature.parameters.items():
|
||||
@@ -181,6 +202,14 @@ def _with_header_project_context(endpoint, route_name: str):
|
||||
if name in body_models:
|
||||
parameter = parameter.replace(annotation=body_models[name][1])
|
||||
parameters.append(parameter)
|
||||
routing_dependency = (
|
||||
get_project_simulation_routing
|
||||
if (
|
||||
endpoint.__module__ in _TIMESCALE_ROUTED_ENDPOINT_MODULES
|
||||
or endpoint.__name__ in _TIMESCALE_ROUTED_ENDPOINT_NAMES
|
||||
)
|
||||
else get_project_business_routing
|
||||
)
|
||||
if not existing_context_parameter:
|
||||
parameters.append(
|
||||
inspect.Parameter(
|
||||
@@ -190,6 +219,14 @@ def _with_header_project_context(endpoint, route_name: str):
|
||||
default=Depends(get_project_context),
|
||||
)
|
||||
)
|
||||
parameters.append(
|
||||
inspect.Parameter(
|
||||
injected_routing_name,
|
||||
kind=inspect.Parameter.KEYWORD_ONLY,
|
||||
annotation=ActiveProjectRouting,
|
||||
default=Depends(routing_dependency),
|
||||
)
|
||||
)
|
||||
if username_parameter or model_has_username:
|
||||
parameters.append(
|
||||
inspect.Parameter(
|
||||
|
||||
@@ -7,7 +7,6 @@ from app.api.v1.endpoints import (
|
||||
audit,
|
||||
burst_detection,
|
||||
burst_location,
|
||||
cache,
|
||||
extension,
|
||||
geocoding,
|
||||
leakage,
|
||||
@@ -53,7 +52,6 @@ from app.api.v1.endpoints.timeseries import (
|
||||
)
|
||||
from app.auth.permissions import (
|
||||
BURST_RUN,
|
||||
ENVIRONMENT_MANAGE,
|
||||
OPTIMIZATION_RUN,
|
||||
RISK_RUN,
|
||||
SCADA_CLEAN,
|
||||
@@ -89,7 +87,6 @@ simulation_access = Depends(
|
||||
|
||||
webgis_view_access = Depends(require_permission(WEBGIS_VIEW))
|
||||
simulation_run_access = Depends(require_permission(SIMULATION_RUN))
|
||||
environment_manage_access = Depends(require_permission(ENVIRONMENT_MANAGE))
|
||||
burst_run_access = Depends(require_permission(BURST_RUN))
|
||||
risk_run_access = Depends(require_permission(RISK_RUN))
|
||||
optimization_run_access = Depends(require_permission(OPTIMIZATION_RUN))
|
||||
@@ -168,11 +165,6 @@ api_router.include_router(
|
||||
tags=["Risk"],
|
||||
dependencies=[risk_run_access],
|
||||
)
|
||||
api_router.include_router(
|
||||
cache.router,
|
||||
tags=["Cache"],
|
||||
dependencies=[environment_manage_access],
|
||||
)
|
||||
api_router.include_router(
|
||||
web_search.router,
|
||||
tags=["Web Search"],
|
||||
|
||||
@@ -16,6 +16,7 @@ from app.infra.db.metadb.repositories.metadata_repository import (
|
||||
MetadataRepository,
|
||||
ProjectDbRouting,
|
||||
)
|
||||
from app.infra.db.project_routing import ActiveProjectRouting
|
||||
|
||||
DB_ROLE_BIZ_DATA = "biz_data"
|
||||
DB_ROLE_IOT_DATA = "iot_data"
|
||||
@@ -99,6 +100,62 @@ async def get_project_context(
|
||||
return await resolve_project_context(x_project_id, current_user, metadata_repo)
|
||||
|
||||
|
||||
async def get_project_business_routing(
|
||||
ctx: ProjectContext = Depends(get_project_context),
|
||||
metadata_repo: MetadataRepository = Depends(get_metadata_repository),
|
||||
) -> ActiveProjectRouting:
|
||||
return await resolve_project_business_routing(ctx, metadata_repo)
|
||||
|
||||
|
||||
async def resolve_project_business_routing(
|
||||
ctx: ProjectContext,
|
||||
metadata_repo: MetadataRepository,
|
||||
) -> ActiveProjectRouting:
|
||||
business = await _get_project_routing(
|
||||
metadata_repo,
|
||||
ctx.project_id,
|
||||
DB_ROLE_BIZ_DATA,
|
||||
DB_TYPE_POSTGRES,
|
||||
"PostgreSQL",
|
||||
)
|
||||
return ActiveProjectRouting(
|
||||
project_code=ctx.project_code,
|
||||
business_dsn=business.dsn,
|
||||
)
|
||||
|
||||
|
||||
async def get_project_simulation_routing(
|
||||
ctx: ProjectContext = Depends(get_project_context),
|
||||
metadata_repo: MetadataRepository = Depends(get_metadata_repository),
|
||||
) -> ActiveProjectRouting:
|
||||
return await resolve_project_simulation_routing(ctx, metadata_repo)
|
||||
|
||||
|
||||
async def resolve_project_simulation_routing(
|
||||
ctx: ProjectContext,
|
||||
metadata_repo: MetadataRepository,
|
||||
) -> ActiveProjectRouting:
|
||||
business = await _get_project_routing(
|
||||
metadata_repo,
|
||||
ctx.project_id,
|
||||
DB_ROLE_BIZ_DATA,
|
||||
DB_TYPE_POSTGRES,
|
||||
"PostgreSQL",
|
||||
)
|
||||
timescale = await _get_project_routing(
|
||||
metadata_repo,
|
||||
ctx.project_id,
|
||||
DB_ROLE_IOT_DATA,
|
||||
DB_TYPE_TIMESCALE,
|
||||
"TimescaleDB",
|
||||
)
|
||||
return ActiveProjectRouting(
|
||||
project_code=ctx.project_code,
|
||||
business_dsn=business.dsn,
|
||||
timescale_dsn=timescale.dsn,
|
||||
)
|
||||
|
||||
|
||||
async def _get_project_routing(
|
||||
metadata_repo: MetadataRepository,
|
||||
project_id: UUID,
|
||||
|
||||
@@ -26,12 +26,6 @@ class Settings(BaseSettings):
|
||||
TIMESCALEDB_DB_PORT: str = "5433"
|
||||
TIMESCALEDB_DB_USER: str = "postgres"
|
||||
TIMESCALEDB_DB_PASSWORD: str = "password"
|
||||
# InfluxDB
|
||||
INFLUXDB_URL: str = "http://localhost:8086"
|
||||
INFLUXDB_TOKEN: str = "token"
|
||||
INFLUXDB_ORG: str = "org"
|
||||
INFLUXDB_BUCKET: str = "bucket"
|
||||
|
||||
# Metadata Database Config (PostgreSQL)
|
||||
METADATA_DB_NAME: str = "system_hub"
|
||||
METADATA_DB_HOST: str = "localhost"
|
||||
|
||||
Vendored
Vendored
-19
@@ -1,19 +0,0 @@
|
||||
import redis
|
||||
import msgpack
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
# Initialize Redis connection
|
||||
redis_client = redis.Redis(host="127.0.0.1", port=6379, db=0)
|
||||
|
||||
def encode_datetime(obj: Any) -> Any:
|
||||
"""Serialize datetime objects to dictionary format."""
|
||||
if isinstance(obj, datetime):
|
||||
return {"__datetime__": True, "as_str": obj.strftime("%Y%m%dT%H:%M:%S.%f")}
|
||||
return obj
|
||||
|
||||
def decode_datetime(obj: Any) -> Any:
|
||||
"""Deserialize dictionary format to datetime objects."""
|
||||
if "__datetime__" in obj:
|
||||
return datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f")
|
||||
return obj
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
||||
from app.core.config import settings
|
||||
|
||||
url = settings.INFLUXDB_URL
|
||||
token = settings.INFLUXDB_TOKEN
|
||||
org = settings.INFLUXDB_ORG
|
||||
@@ -1,33 +0,0 @@
|
||||
from influxdb_client import InfluxDBClient, Point, WriteOptions
|
||||
from influxdb_client.client.query_api import QueryApi
|
||||
import influxdb_info
|
||||
|
||||
# 配置 InfluxDB 连接
|
||||
url = influxdb_info.url
|
||||
token = influxdb_info.token
|
||||
org = influxdb_info.org
|
||||
bucket = "SCADA_data"
|
||||
|
||||
# 创建 InfluxDB 客户端
|
||||
client = InfluxDBClient(url=url, token=token, org=org)
|
||||
|
||||
# 创建查询 API 对象
|
||||
query_api = client.query_api()
|
||||
|
||||
# 构建查询语句
|
||||
query = f'''
|
||||
from(bucket: "{bucket}")
|
||||
|> range(start: -1h)
|
||||
'''
|
||||
|
||||
# 执行查询
|
||||
result = query_api.query(query)
|
||||
print(result)
|
||||
|
||||
# 处理查询结果
|
||||
for table in result:
|
||||
for record in table.records:
|
||||
print(f"Time: {record.get_time()}, Value: {record.get_value()}, Measurement: {record.get_measurement()}, Field: {record.get_field()}")
|
||||
|
||||
# 关闭客户端连接
|
||||
client.close()
|
||||
@@ -20,14 +20,17 @@ def _normalize_postgres_dsn(dsn: str) -> str:
|
||||
scheme, rest = dsn.split("://", 1)
|
||||
if scheme not in ("postgresql", "postgres", "postgresql+psycopg"):
|
||||
return dsn
|
||||
if scheme == "postgresql+psycopg":
|
||||
scheme = "postgresql"
|
||||
normalized_dsn = f"{scheme}://{rest}"
|
||||
if "@" not in rest:
|
||||
return dsn
|
||||
return normalized_dsn
|
||||
userinfo, hostinfo = rest.rsplit("@", 1)
|
||||
if ":" not in userinfo:
|
||||
return dsn
|
||||
return normalized_dsn
|
||||
username, password = userinfo.split(":", 1)
|
||||
if "@" not in password:
|
||||
return dsn
|
||||
return normalized_dsn
|
||||
password = password.replace("@", "%40")
|
||||
return f"{scheme}://{username}:{password}@{hostinfo}"
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ from contextlib import asynccontextmanager
|
||||
from typing import AsyncGenerator, Dict, Optional
|
||||
import psycopg_pool
|
||||
from psycopg.rows import dict_row
|
||||
import app.core.config as postgresql_info
|
||||
from app.infra.db.project_routing import get_project_pgconn_string
|
||||
|
||||
# Configure logging
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -13,6 +13,7 @@ class Database:
|
||||
def __init__(self, db_name=None):
|
||||
self.pool = None
|
||||
self.db_name = db_name
|
||||
self.conninfo = None
|
||||
|
||||
def init_pool(self, db_name=None):
|
||||
"""Initialize the connection pool."""
|
||||
@@ -21,9 +22,10 @@ class Database:
|
||||
|
||||
# Get connection string, handling default case where target_db_name might be None
|
||||
if target_db_name:
|
||||
conn_string = postgresql_info.get_pgconn_string(db_name=target_db_name)
|
||||
conn_string = get_project_pgconn_string(db_name=target_db_name)
|
||||
else:
|
||||
conn_string = postgresql_info.get_pgconn_string()
|
||||
conn_string = get_project_pgconn_string()
|
||||
self.conninfo = conn_string
|
||||
|
||||
try:
|
||||
self.pool = psycopg_pool.AsyncConnectionPool(
|
||||
@@ -75,6 +77,12 @@ async def get_database_instance(db_name: Optional[str] = None) -> Database:
|
||||
if not db_name:
|
||||
return db # 返回默认数据库实例
|
||||
|
||||
expected_conninfo = get_project_pgconn_string(db_name=db_name)
|
||||
existing = _database_instances.get(db_name)
|
||||
if existing is not None and existing.conninfo != expected_conninfo:
|
||||
await existing.close()
|
||||
del _database_instances[db_name]
|
||||
|
||||
if db_name not in _database_instances:
|
||||
# 创建新的数据库实例
|
||||
instance = create_database_instance(db_name)
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import contextmanager
|
||||
from contextvars import ContextVar, Token
|
||||
from dataclasses import dataclass
|
||||
from typing import Iterator
|
||||
|
||||
from psycopg.conninfo import make_conninfo
|
||||
|
||||
from app.core.config import get_pgconn_string, get_timescaledb_pgconn_string
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ActiveProjectRouting:
|
||||
project_code: str
|
||||
business_dsn: str
|
||||
timescale_dsn: str | None = None
|
||||
|
||||
|
||||
_active_project_routing: ContextVar[ActiveProjectRouting | None] = ContextVar(
|
||||
"active_project_routing",
|
||||
default=None,
|
||||
)
|
||||
|
||||
|
||||
def get_active_project_routing() -> ActiveProjectRouting | None:
|
||||
return _active_project_routing.get()
|
||||
|
||||
|
||||
@contextmanager
|
||||
def activate_project_routing(
|
||||
routing: ActiveProjectRouting,
|
||||
) -> Iterator[ActiveProjectRouting]:
|
||||
token: Token[ActiveProjectRouting | None] = _active_project_routing.set(routing)
|
||||
try:
|
||||
yield routing
|
||||
finally:
|
||||
_active_project_routing.reset(token)
|
||||
|
||||
|
||||
def _dsn_for_database(dsn: str, database_name: str) -> str:
|
||||
return make_conninfo(dsn, dbname=database_name)
|
||||
|
||||
|
||||
def get_project_pgconn_string(db_name: str | None = None) -> str:
|
||||
routing = get_active_project_routing()
|
||||
if routing is None:
|
||||
return get_pgconn_string(db_name=db_name)
|
||||
if db_name is None or db_name == routing.project_code:
|
||||
return routing.business_dsn
|
||||
return _dsn_for_database(routing.business_dsn, db_name)
|
||||
|
||||
|
||||
def get_project_timescale_pgconn_string(db_name: str | None = None) -> str:
|
||||
routing = get_active_project_routing()
|
||||
if routing is None:
|
||||
return get_timescaledb_pgconn_string(db_name=db_name)
|
||||
if routing.timescale_dsn is None:
|
||||
raise RuntimeError(
|
||||
f"TimescaleDB routing is not configured for project {routing.project_code}"
|
||||
)
|
||||
# Legacy simulation code used to derive the Timescale database name from
|
||||
# the project code. Project-scoped requests must instead use the complete
|
||||
# iot_data DSN selected by metadata routing.
|
||||
return routing.timescale_dsn
|
||||
@@ -3,7 +3,7 @@ from contextlib import asynccontextmanager
|
||||
from typing import AsyncGenerator, Dict, Optional
|
||||
import psycopg_pool
|
||||
from psycopg.rows import dict_row
|
||||
from app.core.config import get_timescaledb_pgconn_string
|
||||
from app.infra.db.project_routing import get_project_timescale_pgconn_string
|
||||
|
||||
# Configure logging
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -13,6 +13,7 @@ class Database:
|
||||
def __init__(self, db_name=None):
|
||||
self.pool = None
|
||||
self.db_name = db_name
|
||||
self.conninfo = None
|
||||
|
||||
def init_pool(self, db_name=None):
|
||||
"""Initialize the connection pool."""
|
||||
@@ -21,9 +22,10 @@ class Database:
|
||||
|
||||
# Get connection string, handling default case where target_db_name might be None
|
||||
if target_db_name:
|
||||
conn_string = get_timescaledb_pgconn_string(db_name=target_db_name)
|
||||
conn_string = get_project_timescale_pgconn_string(db_name=target_db_name)
|
||||
else:
|
||||
conn_string = get_timescaledb_pgconn_string()
|
||||
conn_string = get_project_timescale_pgconn_string()
|
||||
self.conninfo = conn_string
|
||||
|
||||
try:
|
||||
self.pool = psycopg_pool.AsyncConnectionPool(
|
||||
@@ -54,8 +56,8 @@ class Database:
|
||||
"""Get the TimescaleDB connection string."""
|
||||
target_db_name = db_name or self.db_name
|
||||
if target_db_name:
|
||||
return get_timescaledb_pgconn_string(db_name=target_db_name)
|
||||
return get_timescaledb_pgconn_string()
|
||||
return get_project_timescale_pgconn_string(db_name=target_db_name)
|
||||
return get_project_timescale_pgconn_string()
|
||||
|
||||
@asynccontextmanager
|
||||
async def get_connection(self) -> AsyncGenerator:
|
||||
@@ -84,6 +86,12 @@ async def get_database_instance(db_name: Optional[str] = None) -> Database:
|
||||
if not db_name:
|
||||
return db # 返回默认数据库实例
|
||||
|
||||
expected_conninfo = get_project_timescale_pgconn_string(db_name=db_name)
|
||||
existing = _database_instances.get(db_name)
|
||||
if existing is not None and existing.conninfo != expected_conninfo:
|
||||
await existing.close()
|
||||
del _database_instances[db_name]
|
||||
|
||||
if db_name not in _database_instances:
|
||||
# 创建新的数据库实例
|
||||
instance = create_database_instance(db_name)
|
||||
|
||||
@@ -6,7 +6,7 @@ import psycopg
|
||||
from psycopg import sql
|
||||
from psycopg.rows import dict_row
|
||||
import time
|
||||
from app.core.config import get_timescaledb_pgconn_string
|
||||
from app.infra.db.project_routing import get_project_timescale_pgconn_string
|
||||
from app.infra.db.timescaledb.repositories.scheme import SchemeRepository
|
||||
from app.infra.db.timescaledb.repositories.realtime import RealtimeRepository
|
||||
from app.infra.db.timescaledb.repositories.scada import ScadaRepository
|
||||
@@ -26,9 +26,9 @@ class InternalStorage:
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
conn_string = (
|
||||
get_timescaledb_pgconn_string(db_name=db_name)
|
||||
get_project_timescale_pgconn_string(db_name=db_name)
|
||||
if db_name
|
||||
else get_timescaledb_pgconn_string()
|
||||
else get_project_timescale_pgconn_string()
|
||||
)
|
||||
with psycopg.Connection.connect(conn_string) as conn:
|
||||
RealtimeRepository.store_realtime_simulation_result_sync(
|
||||
@@ -58,9 +58,9 @@ class InternalStorage:
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
conn_string = (
|
||||
get_timescaledb_pgconn_string(db_name=db_name)
|
||||
get_project_timescale_pgconn_string(db_name=db_name)
|
||||
if db_name
|
||||
else get_timescaledb_pgconn_string()
|
||||
else get_project_timescale_pgconn_string()
|
||||
)
|
||||
with psycopg.Connection.connect(conn_string) as conn:
|
||||
SchemeRepository.store_scheme_simulation_result_sync(
|
||||
@@ -99,9 +99,9 @@ class InternalQueries:
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
conn_string = (
|
||||
get_timescaledb_pgconn_string(db_name=db_name)
|
||||
get_project_timescale_pgconn_string(db_name=db_name)
|
||||
if db_name
|
||||
else get_timescaledb_pgconn_string()
|
||||
else get_project_timescale_pgconn_string()
|
||||
)
|
||||
with psycopg.Connection.connect(conn_string) as conn:
|
||||
rows = ScadaRepository.get_scada_by_ids_time_range_sync(
|
||||
@@ -140,9 +140,9 @@ class InternalQueries:
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
conn_string = (
|
||||
get_timescaledb_pgconn_string(db_name=db_name)
|
||||
get_project_timescale_pgconn_string(db_name=db_name)
|
||||
if db_name
|
||||
else get_timescaledb_pgconn_string()
|
||||
else get_project_timescale_pgconn_string()
|
||||
)
|
||||
with psycopg.Connection.connect(conn_string) as conn:
|
||||
rows = ScadaRepository.get_scada_by_ids_time_range_sync(
|
||||
@@ -185,9 +185,9 @@ class InternalQueries:
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
conn_string = (
|
||||
get_timescaledb_pgconn_string(db_name=db_name)
|
||||
get_project_timescale_pgconn_string(db_name=db_name)
|
||||
if db_name
|
||||
else get_timescaledb_pgconn_string()
|
||||
else get_project_timescale_pgconn_string()
|
||||
)
|
||||
with psycopg.Connection.connect(conn_string) as conn:
|
||||
return ScadaRepository.get_latest_scada_time_sync(
|
||||
@@ -286,9 +286,9 @@ class InternalQueries:
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
conn_string = (
|
||||
get_timescaledb_pgconn_string(db_name=db_name)
|
||||
get_project_timescale_pgconn_string(db_name=db_name)
|
||||
if db_name
|
||||
else get_timescaledb_pgconn_string()
|
||||
else get_project_timescale_pgconn_string()
|
||||
)
|
||||
with psycopg.Connection.connect(conn_string) as conn:
|
||||
with conn.cursor(row_factory=dict_row) as cur:
|
||||
|
||||
@@ -4,9 +4,10 @@ from threading import RLock
|
||||
|
||||
import psycopg as pg
|
||||
|
||||
from app.core.config import get_pgconn_string
|
||||
from app.infra.db.project_routing import get_project_pgconn_string
|
||||
|
||||
g_conn_dict: dict[str, pg.Connection] = {}
|
||||
g_conninfo_dict: dict[str, str] = {}
|
||||
_registry_lock = RLock()
|
||||
_project_locks: dict[str, RLock] = {}
|
||||
|
||||
@@ -42,14 +43,18 @@ def _get_project_lock(name: str) -> RLock:
|
||||
|
||||
def open_connection(name: str) -> pg.Connection:
|
||||
with _get_project_lock(name):
|
||||
conninfo = get_project_pgconn_string(db_name=name)
|
||||
connection = g_conn_dict.get(name)
|
||||
if connection is None or not _is_healthy(connection):
|
||||
if (
|
||||
connection is None
|
||||
or g_conninfo_dict.get(name) != conninfo
|
||||
or not _is_healthy(connection)
|
||||
):
|
||||
if connection is not None:
|
||||
_close_connection(connection)
|
||||
connection = pg.connect(
|
||||
conninfo=get_pgconn_string(db_name=name), autocommit=True
|
||||
)
|
||||
connection = pg.connect(conninfo=conninfo, autocommit=True)
|
||||
g_conn_dict[name] = connection
|
||||
g_conninfo_dict[name] = conninfo
|
||||
return connection
|
||||
|
||||
|
||||
@@ -60,6 +65,12 @@ def is_connection_open(name: str) -> bool:
|
||||
return False
|
||||
if not _is_healthy(connection):
|
||||
del g_conn_dict[name]
|
||||
g_conninfo_dict.pop(name, None)
|
||||
_close_connection(connection)
|
||||
return False
|
||||
if g_conninfo_dict.get(name) != get_project_pgconn_string(db_name=name):
|
||||
del g_conn_dict[name]
|
||||
g_conninfo_dict.pop(name, None)
|
||||
_close_connection(connection)
|
||||
return False
|
||||
return True
|
||||
@@ -68,6 +79,7 @@ def is_connection_open(name: str) -> bool:
|
||||
def close_connection(name: str) -> None:
|
||||
with _get_project_lock(name):
|
||||
connection = g_conn_dict.pop(name, None)
|
||||
g_conninfo_dict.pop(name, None)
|
||||
if connection is not None:
|
||||
_close_connection(connection)
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ from .connection import (
|
||||
is_connection_open,
|
||||
open_connection,
|
||||
)
|
||||
from app.core.config import get_pgconn_string, get_pg_config, get_pg_password
|
||||
from app.core.config import get_pg_config, get_pg_password
|
||||
from app.infra.db.project_routing import get_project_pgconn_string
|
||||
|
||||
# no undo/redo
|
||||
|
||||
@@ -16,7 +17,7 @@ _server_databases = ["template0", "template1", "postgres", "project"]
|
||||
|
||||
def list_project() -> list[str]:
|
||||
ps = []
|
||||
with pg.connect(conninfo=get_pgconn_string(), autocommit=True) as conn:
|
||||
with pg.connect(conninfo=get_project_pgconn_string(), autocommit=True) as conn:
|
||||
with conn.cursor(row_factory=dict_row) as cur:
|
||||
for p in cur.execute(
|
||||
f"select datname from pg_database where datname <> 'postgres' and datname <> 'template0' and datname <> 'template1' and datname <> 'project'"
|
||||
@@ -27,7 +28,7 @@ def list_project() -> list[str]:
|
||||
|
||||
def have_project(name: str) -> bool:
|
||||
with pg.connect(
|
||||
conninfo=get_pgconn_string(db_name="postgres"), autocommit=True
|
||||
conninfo=get_project_pgconn_string(db_name="postgres"), autocommit=True
|
||||
) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("select 1 from pg_database where datname = %s", (name,))
|
||||
@@ -38,7 +39,7 @@ def copy_project(source: str, new: str) -> None:
|
||||
close_connection(source)
|
||||
|
||||
with pg.connect(
|
||||
conninfo=get_pgconn_string(db_name="postgres"), autocommit=True
|
||||
conninfo=get_project_pgconn_string(db_name="postgres"), autocommit=True
|
||||
) as admin_conn:
|
||||
with admin_conn.cursor() as cur:
|
||||
cur.execute(
|
||||
@@ -131,7 +132,9 @@ class CopyProjectEx:
|
||||
connection.commit()
|
||||
|
||||
def __call__(self, source: str, new_db: str, excluded_tables: [str] = None) -> None:
|
||||
source_connection = pg.connect(conninfo=get_pgconn_string(), autocommit=True)
|
||||
source_connection = pg.connect(
|
||||
conninfo=get_project_pgconn_string(), autocommit=True
|
||||
)
|
||||
|
||||
self.create_database(source_connection, new_db)
|
||||
|
||||
@@ -140,7 +143,7 @@ class CopyProjectEx:
|
||||
source_connection.close()
|
||||
|
||||
new_db_connection = pg.connect(
|
||||
conninfo=get_pgconn_string(db_name=new_db), autocommit=True
|
||||
conninfo=get_project_pgconn_string(db_name=new_db), autocommit=True
|
||||
)
|
||||
self.init_operation_table(new_db_connection, excluded_tables)
|
||||
new_db_connection.close()
|
||||
@@ -151,7 +154,7 @@ def create_project(name: str) -> None:
|
||||
|
||||
|
||||
def delete_project(name: str) -> None:
|
||||
with pg.connect(conninfo=get_pgconn_string(), autocommit=True) as conn:
|
||||
with pg.connect(conninfo=get_project_pgconn_string(), autocommit=True) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
f"select pg_terminate_backend(pid) from pg_stat_activity where datname = '{name}'"
|
||||
@@ -161,7 +164,7 @@ def delete_project(name: str) -> None:
|
||||
|
||||
def clean_project(excluded: list[str] = []) -> None:
|
||||
projects = list_project()
|
||||
with pg.connect(conninfo=get_pgconn_string(), autocommit=True) as conn:
|
||||
with pg.connect(conninfo=get_project_pgconn_string(), autocommit=True) as conn:
|
||||
with conn.cursor(row_factory=dict_row) as cur:
|
||||
row = cur.execute(f"select current_database()").fetchone()
|
||||
if row != None:
|
||||
|
||||
@@ -23,7 +23,6 @@ non_realtime_region_patterns = {} # 基于source_outflow_region进行区分
|
||||
realtime_region_pipe_flow_and_demand_id = {} # 基于source_outflow_region搜索该分区中的实时pipe_flow和demand的api_query_id,后续用region的流量 - 实时流量计的流量
|
||||
realtime_region_pipe_flow_and_demand_patterns = {} # 基于source_outflow_region搜索该分区中的实时pipe_flow和demand的associated_pattern,后续用region的流量 - 实时流量计的流量
|
||||
# ---------------------------------------------------------
|
||||
# influxdb_api.py中的全局变量
|
||||
# 全局变量,用于存储不同类型的realtime api_query_id
|
||||
reservoir_liquid_level_realtime_ids = []
|
||||
tank_liquid_level_realtime_ids = []
|
||||
|
||||
@@ -5,8 +5,7 @@ import chardet
|
||||
import psycopg
|
||||
from psycopg import sql
|
||||
|
||||
import app.services.project_info as project_info
|
||||
from app.core.config import get_pgconn_string
|
||||
from app.infra.db.project_routing import get_project_pgconn_string
|
||||
from app.services.tjnetwork import read_inp
|
||||
|
||||
|
||||
@@ -15,13 +14,14 @@ from app.services.tjnetwork import read_inp
|
||||
############################################################
|
||||
|
||||
|
||||
def network_update(file_path: str) -> None:
|
||||
def network_update(file_path: str, project_code: str) -> None:
|
||||
"""
|
||||
更新pg数据库中的inp文件
|
||||
:param file_path: inp文件
|
||||
:param project_code: 元数据项目代码
|
||||
:return:
|
||||
"""
|
||||
read_inp("szh", file_path)
|
||||
read_inp(project_code, file_path)
|
||||
|
||||
csv_path = "./history_pattern_flow.csv"
|
||||
|
||||
@@ -51,8 +51,7 @@ def network_update(file_path: str) -> None:
|
||||
if os.path.exists(csv_path):
|
||||
print(f"history_patterns_flows文件存在,开始处理...")
|
||||
|
||||
# 连接到 PostgreSQL 数据库(这里是数据库 "bb")
|
||||
with psycopg.connect(f"dbname={project_info.name} host=127.0.0.1") as conn:
|
||||
with psycopg.connect(get_project_pgconn_string(project_code)) as conn:
|
||||
with conn.cursor() as cur:
|
||||
with open(csv_path, newline="", encoding="utf-8-sig") as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
@@ -92,7 +91,7 @@ def submit_scada_info(name: str, coord_id: str) -> None:
|
||||
print(f"检测到的文件编码:{file_encoding}")
|
||||
try:
|
||||
# 动态替换数据库名称
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
|
||||
# 连接到 PostgreSQL 数据库(这里是数据库 "bb")
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
|
||||
@@ -7,7 +7,7 @@ import pandas as pd
|
||||
import psycopg
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
from app.core.config import get_pgconn_string
|
||||
from app.infra.db.project_routing import get_project_pgconn_string
|
||||
from app.services.time_api import parse_utc_time
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ def scheme_name_exists(name: str, scheme_name: str) -> bool:
|
||||
:return: 如果存在返回 True,否则返回 False
|
||||
"""
|
||||
try:
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
@@ -57,7 +57,7 @@ def store_scheme_info(
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
sql = """
|
||||
@@ -93,7 +93,7 @@ def delete_scheme_info(name: str, scheme_name: str) -> None:
|
||||
:param scheme_name: 要删除的方案名称
|
||||
"""
|
||||
try:
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
# 使用参数化查询删除方案记录
|
||||
@@ -121,7 +121,7 @@ def query_scheme_list(
|
||||
"""
|
||||
try:
|
||||
# 动态替换数据库名称
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
# 连接到 PostgreSQL 数据库(这里是数据库 "bb")
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
@@ -203,7 +203,7 @@ def query_scheme_detail(
|
||||
scheme_type,
|
||||
)
|
||||
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
if scheme_type:
|
||||
@@ -255,7 +255,7 @@ def store_leakage_identify_result(
|
||||
run_status: str = "completed",
|
||||
error_message: str | None = None,
|
||||
) -> None:
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
@@ -299,7 +299,7 @@ def query_leakage_identify_schemes(
|
||||
scheme_type: str = "dma_leak_identification",
|
||||
query_date: date | None = None,
|
||||
) -> list[dict]:
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
if query_date is None:
|
||||
@@ -343,7 +343,7 @@ def query_leakage_identify_schemes(
|
||||
|
||||
|
||||
def query_leakage_identify_scheme_detail(name: str, scheme_name: str) -> dict:
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
@@ -400,7 +400,7 @@ def query_burst_location_schemes(
|
||||
scheme_type: str = "burst_location",
|
||||
query_date: date | None = None,
|
||||
) -> list[dict]:
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
if query_date is None:
|
||||
@@ -444,7 +444,7 @@ def query_burst_location_schemes(
|
||||
|
||||
|
||||
def query_burst_location_scheme_detail(name: str, scheme_name: str) -> dict:
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
@@ -479,7 +479,7 @@ def query_burst_detection_schemes(
|
||||
scheme_type: str = "burst_detection",
|
||||
query_date: date | None = None,
|
||||
) -> list[dict]:
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
if query_date is None:
|
||||
@@ -523,7 +523,7 @@ def query_burst_detection_schemes(
|
||||
|
||||
|
||||
def query_burst_detection_scheme_detail(name: str, scheme_name: str) -> dict:
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
@@ -564,7 +564,7 @@ def upload_shp_to_pg(name: str, table_name: str, role: str, shp_file_path: str):
|
||||
"""
|
||||
try:
|
||||
# 动态连接到指定的数据库
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
# 读取 Shapefile 文件
|
||||
gdf = gpd.read_file(shp_file_path)
|
||||
@@ -604,7 +604,7 @@ def submit_risk_probability_result(name: str, result_file_path: str) -> None:
|
||||
|
||||
try:
|
||||
# 动态替换数据库名称
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
|
||||
# 连接到 PostgreSQL 数据库
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
|
||||
+10
-11
@@ -28,14 +28,13 @@ import pytz
|
||||
import requests
|
||||
import time
|
||||
from typing import Optional, Tuple
|
||||
import app.infra.db.influxdb.api as influxdb_api
|
||||
import typing
|
||||
import psycopg
|
||||
import logging
|
||||
import app.services.globals as globals
|
||||
import app.services.project_info as project_info
|
||||
from app.services.time_api import parse_beijing_time, parse_clock_duration_seconds
|
||||
from app.core.config import get_pgconn_string
|
||||
from app.infra.db.project_routing import get_project_pgconn_string
|
||||
from app.infra.db.timescaledb.internal_queries import (
|
||||
InternalQueries as TimescaleInternalQueries,
|
||||
)
|
||||
@@ -55,7 +54,7 @@ def query_corresponding_element_id_and_query_id(name: str) -> None:
|
||||
:return:
|
||||
"""
|
||||
# 连接数据库
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
try:
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
@@ -100,7 +99,7 @@ def query_corresponding_pattern_id_and_query_id(name: str) -> None:
|
||||
:return:
|
||||
"""
|
||||
# 连接数据库
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
try:
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
@@ -140,7 +139,7 @@ def query_non_realtime_region(name: str) -> dict:
|
||||
"""
|
||||
source_outflow_regions = [] # 用于存储所有 region(包含重复的)
|
||||
# 构建连接字符串
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
try:
|
||||
# 连接到数据库
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
@@ -217,7 +216,7 @@ def query_non_realtime_region_patterns(
|
||||
region_tuple_to_key = {
|
||||
frozenset(ids): region for region, ids in globals.source_outflow_region.items()
|
||||
}
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
try:
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
@@ -305,7 +304,7 @@ def query_realtime_region_pipe_flow_and_demand_id(
|
||||
region_tuple_to_key = {
|
||||
frozenset(ids): region for region, ids in globals.source_outflow_region.items()
|
||||
}
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
try:
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
@@ -377,7 +376,7 @@ def query_pipe_flow_region_patterns(
|
||||
:param column_prefix: 需要提取的列的前缀
|
||||
:return: pipe_flow_region_patterns 字典
|
||||
"""
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
try:
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
@@ -440,7 +439,7 @@ def query_SCADA_ID_corresponding_info(name: str, SCADA_ID: str) -> dict:
|
||||
:param SCADA_ID: SCADA设备的ID
|
||||
:return: 包含associated_element_id和api_query_id的字典
|
||||
"""
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
try:
|
||||
# 使用 psycopg.connect 创建连接
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
@@ -496,7 +495,7 @@ def get_source_outflow_region_id(
|
||||
"No associated_source_outflow_id found in source_outflow_region."
|
||||
)
|
||||
return globals.source_outflow_region_id
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
try:
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
@@ -553,7 +552,7 @@ def get_realtime_region_patterns(
|
||||
globals.realtime_region_pipe_flow_and_demand_patterns = {
|
||||
region: [] for region in globals.realtime_region_pipe_flow_and_demand_id.keys()
|
||||
}
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
conn_string = get_project_pgconn_string(db_name=name)
|
||||
try:
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
|
||||
Reference in New Issue
Block a user