gencow 0.1.97 → 0.1.99

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/gencow.mjs CHANGED
@@ -3523,6 +3523,7 @@ process.exit(0);
3523
3523
  let followFailures = 0;
3524
3524
  let followTimer = null;
3525
3525
  let followWs = null;
3526
+ let followOpenedAt = 0; // 안정 연결 판정용 (open 시각)
3526
3527
 
3527
3528
  async function connectFollowStream() {
3528
3529
  const wsUrl = `ws://localhost:${port}/ws`;
@@ -3538,7 +3539,8 @@ process.exit(0);
3538
3539
  }
3539
3540
 
3540
3541
  followWs.on("open", () => {
3541
- followFailures = 0; // 성공 실패 카운터 리셋
3542
+ // 카운터 리셋은 close 이벤트에서 안정 연결 판정 후 수행
3543
+ followOpenedAt = Date.now();
3542
3544
  success("Connected — streaming logs...\n");
3543
3545
  followWs.send(JSON.stringify({ type: "log:subscribe" }));
3544
3546
  });
@@ -3567,6 +3569,11 @@ process.exit(0);
3567
3569
  });
3568
3570
 
3569
3571
  followWs.on("close", () => {
3572
+ // 5초 이상 유지된 안정 연결이면 카운터 리셋 (정상 운영 중 일시 끊김)
3573
+ const wasStable = (Date.now() - followOpenedAt) > 5000;
3574
+ if (wasStable) {
3575
+ followFailures = 0;
3576
+ }
3570
3577
  followFailures++;
3571
3578
  if (followFailures > FOLLOW_MAX_FAILURES) {
3572
3579
  error(`연결 불가 — 앱 상태를 확인하세요.`);
@@ -3988,6 +3995,7 @@ process.exit(0);
3988
3995
  // ── WebSocket 실시간 로그 스트리밍 ─────────────────
3989
3996
  let logWs = null;
3990
3997
  let reconnectTimer = null;
3998
+ let logWsOpenedAt = 0; // 안정 연결 판정용 (open 시각)
3991
3999
 
3992
4000
  async function connectLogStream() {
3993
4001
  const { WebSocket: WS } = await import("ws");
@@ -4002,7 +4010,8 @@ process.exit(0);
4002
4010
  }
4003
4011
 
4004
4012
  logWs.on("open", () => {
4005
- reconnectFailures = 0; // 연결 성공 실패 카운터 리셋
4013
+ // 카운터 리셋은 close 이벤트에서 안정 연결 판정 수행
4014
+ logWsOpenedAt = Date.now();
4006
4015
  log(`${DIM}${new Date().toLocaleTimeString("en-US", { hour12: false })}${RESET} ${GREEN}[log]${RESET} 로그 스트리밍 연결됨`);
4007
4016
  logWs.send(JSON.stringify({ type: "log:subscribe" }));
4008
4017
  });
@@ -4020,6 +4029,11 @@ process.exit(0);
4020
4029
  });
4021
4030
 
4022
4031
  logWs.on("close", () => {
4032
+ // 5초 이상 유지된 안정 연결이면 카운터 리셋 (정상 운영 중 일시 끊김)
4033
+ const wasStable = (Date.now() - logWsOpenedAt) > 5000;
4034
+ if (wasStable) {
4035
+ reconnectFailures = 0;
4036
+ }
4023
4037
  reconnectFailures++;
4024
4038
  if (reconnectFailures > MAX_RECONNECT_FAILURES) {
4025
4039
  warn(`[log] 로그 스트리밍 ${MAX_RECONNECT_FAILURES}회 연속 실패. 재연결 중단.`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gencow",
3
- "version": "0.1.97",
3
+ "version": "0.1.99",
4
4
  "description": "Gencow — AI Backend Engine",
5
5
  "type": "module",
6
6
  "bin": {
package/server/index.js CHANGED
@@ -82529,6 +82529,7 @@ async function main() {
82529
82529
  const { addProxyMetric } = await import(resolve5(functionsPath, "../src/proxy-metrics.ts"));
82530
82530
  const { apps: appsTable } = await import(resolve5(functionsPath, "schema.ts"));
82531
82531
  const { eq: eqOp } = await import("drizzle-orm");
82532
+ const { getAppPort: getLivePort } = await import(resolve5(functionsPath, "../src/provisioner.ts"));
82532
82533
  const domainCache = /* @__PURE__ */ new Map();
82533
82534
  const CACHE_TTL = 5 * 60 * 1e3;
82534
82535
  const NEG_CACHE_TTL = 60 * 1e3;
@@ -82568,7 +82569,7 @@ async function main() {
82568
82569
  return c.json({ error: `App "${appName}" not found` }, 404);
82569
82570
  }
82570
82571
  const appRow = rows[0];
82571
- const appPort = appRow.port;
82572
+ const appPort = getLivePort(appName) || appRow.port;
82572
82573
  const url3 = new URL(c.req.url);
82573
82574
  const pathname = url3.pathname;
82574
82575
  if (appRow.status === "sleeping") {
@@ -82589,6 +82590,9 @@ async function main() {
82589
82590
  const hasStatic = !!appRow.staticDeployedAt;
82590
82591
  const upgradeHeader = (c.req.header("upgrade") || "").toLowerCase();
82591
82592
  if (upgradeHeader === "websocket" && bunServer) {
82593
+ if (!hasBackend) {
82594
+ return c.json({ error: "WebSocket not available \u2014 this app has no backend process" }, 426);
82595
+ }
82592
82596
  const upgraded = bunServer.upgrade(c.req.raw, {
82593
82597
  data: { proxyPort: appPort, proxyPath: pathname }
82594
82598
  });