修复 prefect中psql报错

This commit is contained in:
2026-05-12 10:15:46 +08:00
parent c50d697a95
commit 989fe75485
2 changed files with 31 additions and 36 deletions
+17 -36
View File
@@ -2,10 +2,10 @@ from __future__ import annotations
import csv import csv
import io import io
import os
import subprocess
from typing import Any from typing import Any
import psycopg2
from .settings import AppConfig from .settings import AppConfig
from .specs import BrandSyncTarget from .specs import BrandSyncTarget
from .sql import DEFAULT_SYNC_TARGET, POSTGRES_QUERY, build_postgres_query from .sql import DEFAULT_SYNC_TARGET, POSTGRES_QUERY, build_postgres_query
@@ -27,40 +27,21 @@ def query_postgres(
warehouse_keys=active_warehouse_keys, warehouse_keys=active_warehouse_keys,
) )
) )
env = os.environ.copy() output = io.StringIO()
env["PGPASSWORD"] = config.analytics_db_password
command = [
"/usr/local/bin/psql",
"-h",
config.analytics_db_host,
"-p",
config.analytics_db_port,
"-U",
config.analytics_db_user,
"-d",
config.analytics_db_name,
"-v",
"ON_ERROR_STOP=1",
"-c",
"SET TIME ZONE 'Asia/Shanghai';",
"-c",
f"COPY ({query}) TO STDOUT WITH CSV HEADER",
]
try: try:
completed = subprocess.run( with psycopg2.connect(
command, host=config.analytics_db_host,
check=True, port=config.analytics_db_port,
capture_output=True, user=config.analytics_db_user,
text=True, password=config.analytics_db_password,
env=env, dbname=config.analytics_db_name,
) ) as conn:
except subprocess.CalledProcessError as exc: with conn.cursor() as cur:
detail = exc.stderr.strip() or exc.stdout.strip() cur.execute("SET TIME ZONE 'Asia/Shanghai';")
raise RuntimeError(f"PostgreSQL 查询失败: {detail}") from exc cur.copy_expert(f"COPY ({query}) TO STDOUT WITH CSV HEADER", output)
except psycopg2.Error as exc:
raise RuntimeError(f"PostgreSQL 查询失败: {exc}") from exc
cleaned_output = "\n".join( output.seek(0)
line for line in completed.stdout.splitlines() if line.strip() and line.strip() != "SET" rows = list(csv.DictReader(output))
)
rows = list(csv.DictReader(io.StringIO(cleaned_output)))
return {"row_count": len(rows), "rows": rows} return {"row_count": len(rows), "rows": rows}
+14
View File
@@ -28,7 +28,19 @@ from prefect import flow, get_run_logger, task
from inventory_analytics.logging_utils import exception_fields from inventory_analytics.logging_utils import exception_fields
from inventory_analytics.channel_inventory_sync.entrypoint import main as channel_inventory_sync_main from inventory_analytics.channel_inventory_sync.entrypoint import main as channel_inventory_sync_main
from inventory_analytics.channel_inventory_sync.entrypoint import LOG_FILE as CHANNEL_INVENTORY_SYNC_LOG_FILE
from inventory_analytics.batch_inventory_report.cli import main as batch_inventory_report_main from inventory_analytics.batch_inventory_report.cli import main as batch_inventory_report_main
from inventory_analytics.batch_inventory_report.service import LOG_FILE as BATCH_INVENTORY_REPORT_LOG_FILE
def read_log_tail(log_file: Path, line_count: int = 80) -> str:
try:
lines = log_file.read_text(encoding="utf-8", errors="replace").splitlines()
except FileNotFoundError:
return f"日志文件不存在: {log_file.name}"
except Exception as exc: # noqa: BLE001
return f"读取日志文件失败: {exc.__class__.__name__}: {exc}"
return "\n".join(lines[-line_count:]) if lines else f"日志文件为空: {log_file.name}"
@task(name="run-channel-inventory-sync") @task(name="run-channel-inventory-sync")
@@ -58,6 +70,7 @@ def run_channel_inventory_sync_task() -> None:
root_logger.setLevel(original_level) root_logger.setLevel(original_level)
if exit_code != 0: if exit_code != 0:
logger.error("渠道库存统计失败,退出码=%s", exit_code) logger.error("渠道库存统计失败,退出码=%s", exit_code)
logger.error("渠道库存统计日志尾部:\n%s", read_log_tail(CHANNEL_INVENTORY_SYNC_LOG_FILE))
raise RuntimeError(f"渠道库存统计执行失败,退出码: {exit_code}") raise RuntimeError(f"渠道库存统计执行失败,退出码: {exit_code}")
logger.info("渠道库存统计完成,耗时毫秒=%s", int((time.monotonic() - started_at) * 1000)) logger.info("渠道库存统计完成,耗时毫秒=%s", int((time.monotonic() - started_at) * 1000))
@@ -107,6 +120,7 @@ def run_batch_inventory_report_task(
root_logger.setLevel(original_level) root_logger.setLevel(original_level)
if exit_code != 0: if exit_code != 0:
logger.error("批次库存统计失败,退出码=%s", exit_code) logger.error("批次库存统计失败,退出码=%s", exit_code)
logger.error("批次库存统计日志尾部:\n%s", read_log_tail(BATCH_INVENTORY_REPORT_LOG_FILE))
raise RuntimeError(f"批次库存统计报表执行失败,退出码: {exit_code}") raise RuntimeError(f"批次库存统计报表执行失败,退出码: {exit_code}")
logger.info("批次库存统计完成,耗时毫秒=%s", int((time.monotonic() - started_at) * 1000)) logger.info("批次库存统计完成,耗时毫秒=%s", int((time.monotonic() - started_at) * 1000))