预热线程增加 I/O 异常保护,避免进程关闭时 file closed 报错
This commit is contained in:
@@ -8,7 +8,6 @@ import {
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
GraduationCap,
|
||||
LineChart,
|
||||
Menu,
|
||||
Search,
|
||||
Table2,
|
||||
@@ -473,7 +472,6 @@ function PolyWeatherTerminal({
|
||||
|
||||
const NAV_ITEMS = [
|
||||
{ key: "contracts", Icon: Table2, labelEn: "Contracts", labelZh: "天气合约" },
|
||||
{ key: "signals", Icon: LineChart, labelEn: "Signals", labelZh: "交易信号" },
|
||||
{ key: "markets", Icon: Activity, labelEn: "Markets", labelZh: "市场概览" },
|
||||
{ key: "training", Icon: GraduationCap, labelEn: "Training", labelZh: "训练数据" },
|
||||
];
|
||||
|
||||
@@ -364,6 +364,27 @@ function buildChartDomain(
|
||||
return [Number((min - padding).toFixed(1)), Number((max + padding).toFixed(1))];
|
||||
}
|
||||
|
||||
function buildProbRefLines(row: ScanOpportunityRow | null) {
|
||||
const buckets = row?.distribution_full?.length
|
||||
? row.distribution_full
|
||||
: row?.distribution_preview;
|
||||
if (!buckets?.length) return [];
|
||||
const maxProb = Math.max(...buckets.map((b) => b.model_probability ?? 0), 0.01);
|
||||
return buckets
|
||||
.filter((b) => validNumber(b.value) !== null && (b.model_probability ?? 0) > 0)
|
||||
.map((b) => {
|
||||
const prob = b.model_probability ?? 0;
|
||||
const intensity = prob / maxProb; // 0..1
|
||||
return {
|
||||
y: b.value!,
|
||||
prob,
|
||||
stroke: `rgba(37, 99, 235, ${(0.12 + intensity * 0.55).toFixed(2)})`,
|
||||
width: 0.6 + intensity * 2.4,
|
||||
label: `${(prob * 100).toFixed(0)}%`,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function LiveTemperatureThresholdChart({
|
||||
isEn,
|
||||
row,
|
||||
@@ -414,6 +435,7 @@ export function LiveTemperatureThresholdChart({
|
||||
.slice(0, 5)
|
||||
.map((item) => ({ ...item, ...seriesStats(item.values) }));
|
||||
const marketTemperatureTicks = useMemo(() => buildMarketTemperatureOptions(row), [row]);
|
||||
const probRefLines = useMemo(() => buildProbRefLines(row), [row]);
|
||||
const chartDomain = useMemo(
|
||||
() => buildChartDomain(marketTemperatureTicks, series),
|
||||
[marketTemperatureTicks, series],
|
||||
@@ -489,6 +511,19 @@ export function LiveTemperatureThresholdChart({
|
||||
label={{ value: `UMA ${threshold.toFixed(1)}°`, fill: "#f97316", fontSize: 10, position: "left" }}
|
||||
/>
|
||||
)}
|
||||
{probRefLines.map((item, i) => (
|
||||
<ReferenceLine
|
||||
key={`prob-${i}`}
|
||||
y={item.y}
|
||||
stroke={item.stroke}
|
||||
strokeWidth={item.width}
|
||||
label={
|
||||
item.prob >= 0.15
|
||||
? { value: item.label, fill: "#2563eb", fontSize: 9, position: "insideRight" }
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
))}
|
||||
<Tooltip
|
||||
contentStyle={{
|
||||
border: "1px solid #cbd5e1",
|
||||
|
||||
@@ -1581,21 +1581,31 @@ def start_scan_terminal_prewarm() -> None:
|
||||
def _run():
|
||||
started = time.time()
|
||||
ok = 0
|
||||
workers = max(1, min(SCAN_TERMINAL_MAX_WORKERS, len(city_names)))
|
||||
with ThreadPoolExecutor(max_workers=workers) as ex:
|
||||
futures = {ex.submit(_warm_one, c): c for c in city_names}
|
||||
for f in as_completed(futures):
|
||||
try:
|
||||
f.result()
|
||||
ok += 1
|
||||
except Exception:
|
||||
pass
|
||||
elapsed = int(time.time() - started)
|
||||
logger.info(
|
||||
"scan terminal pre-warm finished ok={}/{} elapsed={}s",
|
||||
ok,
|
||||
len(city_names),
|
||||
elapsed,
|
||||
)
|
||||
try:
|
||||
workers = max(1, min(SCAN_TERMINAL_MAX_WORKERS, len(city_names)))
|
||||
with ThreadPoolExecutor(max_workers=workers) as ex:
|
||||
futures = {ex.submit(_warm_one, c): c for c in city_names}
|
||||
for f in as_completed(futures):
|
||||
try:
|
||||
f.result()
|
||||
ok += 1
|
||||
except Exception:
|
||||
pass
|
||||
elapsed = int(time.time() - started)
|
||||
logger.info(
|
||||
"scan terminal pre-warm finished ok={}/{} elapsed={}s",
|
||||
ok,
|
||||
len(city_names),
|
||||
elapsed,
|
||||
)
|
||||
except (ValueError, OSError, IOError):
|
||||
# Process is shutting down — file handles / threads may be closed
|
||||
logger.info(
|
||||
"scan terminal pre-warm interrupted (shutdown) ok={}/{}",
|
||||
ok,
|
||||
len(city_names),
|
||||
)
|
||||
except Exception:
|
||||
logger.exception("scan terminal pre-warm failed")
|
||||
|
||||
threading.Thread(target=_run, name="scan-prewarm", daemon=True).start()
|
||||
|
||||
Reference in New Issue
Block a user