gencow 0.1.151 → 0.1.152

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gencow",
3
- "version": "0.1.151",
3
+ "version": "0.1.152",
4
4
  "description": "Gencow — AI Backend Engine",
5
5
  "type": "module",
6
6
  "bin": {
package/server/index.js CHANGED
@@ -88535,14 +88535,20 @@ var DEFAULT_TIMEOUT_RESTART_THRESHOLD = 3;
88535
88535
  var DEFAULT_TIMEOUT_RESTART_WINDOW_MS = 6e4;
88536
88536
  var DEFAULT_TIMEOUT_RESTART_DELAY_MS = 250;
88537
88537
  var DEFAULT_TIMEOUT_RESTART_KINDS = ["query", "mutation"];
88538
+ var DEFAULT_FUNCTION_SLOW_LOG_MS = 1e4;
88538
88539
  var timeoutWindowStartMs = 0;
88539
88540
  var timeoutCountInWindow = 0;
88540
88541
  var timeoutRestartScheduled = false;
88541
88542
  var timeoutFunctionNames = [];
88543
+ var functionInvocationSequence = 0;
88542
88544
  function parsePositiveInteger(value, fallback) {
88543
88545
  const parsed = Number(value);
88544
88546
  return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
88545
88547
  }
88548
+ function parseNonNegativeInteger(value, fallback) {
88549
+ const parsed = Number(value);
88550
+ return Number.isInteger(parsed) && parsed >= 0 ? parsed : fallback;
88551
+ }
88546
88552
  function parseRestartKinds(value) {
88547
88553
  if (!value?.trim()) return [...DEFAULT_TIMEOUT_RESTART_KINDS];
88548
88554
  const allowed = /* @__PURE__ */ new Set(["query", "mutation", "httpAction", "cron"]);
@@ -88569,6 +88575,20 @@ function resolveFunctionTimeoutRestartPolicy(env2 = process.env) {
88569
88575
  kinds: parseRestartKinds(env2.GENCOW_FUNCTION_TIMEOUT_RESTART_KINDS)
88570
88576
  };
88571
88577
  }
88578
+ function resolveFunctionSlowLogMs(env2 = process.env) {
88579
+ return parseNonNegativeInteger(env2.GENCOW_FUNCTION_SLOW_LOG_MS, DEFAULT_FUNCTION_SLOW_LOG_MS);
88580
+ }
88581
+ function nextFunctionInvocationId() {
88582
+ functionInvocationSequence = functionInvocationSequence >= Number.MAX_SAFE_INTEGER ? 1 : functionInvocationSequence + 1;
88583
+ return `${Date.now().toString(36)}-${functionInvocationSequence}`;
88584
+ }
88585
+ function formatErrorForRuntimeLog(error) {
88586
+ const record = error;
88587
+ const name = typeof record?.name === "string" ? record.name : "Error";
88588
+ const code = typeof record?.code === "string" ? ` code=${record.code}` : "";
88589
+ const message = typeof record?.message === "string" ? record.message.replace(/\s+/g, " ").slice(0, 300) : String(error).replace(/\s+/g, " ").slice(0, 300);
88590
+ return `name=${name}${code} message="${message}"`;
88591
+ }
88572
88592
  function recordFunctionTimeout(event, runtime = {}) {
88573
88593
  const env2 = runtime.env ?? process.env;
88574
88594
  const policy = resolveFunctionTimeoutRestartPolicy(env2);
@@ -88600,13 +88620,40 @@ function recordFunctionTimeout(event, runtime = {}) {
88600
88620
  }
88601
88621
  async function executeWithTimeout(fn, type, functionName, timeouts = FUNCTION_TIMEOUTS, restartRuntime) {
88602
88622
  const timeoutMs = timeouts[type];
88623
+ const invocationId = nextFunctionInvocationId();
88624
+ const startedAt = Date.now();
88625
+ const logger2 = restartRuntime?.logger ?? console;
88626
+ const slowLogMs = resolveFunctionSlowLogMs(restartRuntime?.env);
88603
88627
  const controller = new AbortController();
88604
88628
  const timer = setTimeout(() => controller.abort(), timeoutMs);
88629
+ let timedOut = false;
88630
+ const work = Promise.resolve().then(fn);
88631
+ work.then(
88632
+ () => {
88633
+ if (!timedOut) return;
88634
+ const elapsedMs = Date.now() - startedAt;
88635
+ logger2.warn(
88636
+ `[runtime] function completed after timeout id=${invocationId} type=${type} name="${functionName}" elapsedMs=${elapsedMs} timeoutMs=${timeoutMs}`
88637
+ );
88638
+ },
88639
+ (error) => {
88640
+ if (!timedOut) return;
88641
+ const elapsedMs = Date.now() - startedAt;
88642
+ logger2.error(
88643
+ `[runtime] function failed after timeout id=${invocationId} type=${type} name="${functionName}" elapsedMs=${elapsedMs} timeoutMs=${timeoutMs} ${formatErrorForRuntimeLog(error)}`
88644
+ );
88645
+ }
88646
+ );
88605
88647
  try {
88606
- return await Promise.race([
88607
- fn(),
88648
+ const result2 = await Promise.race([
88649
+ work,
88608
88650
  new Promise((_3, reject2) => {
88609
88651
  controller.signal.addEventListener("abort", () => {
88652
+ timedOut = true;
88653
+ const elapsedMs2 = Date.now() - startedAt;
88654
+ logger2.error(
88655
+ `[runtime] function timeout id=${invocationId} type=${type} name="${functionName}" elapsedMs=${elapsedMs2} timeoutMs=${timeoutMs}`
88656
+ );
88610
88657
  recordFunctionTimeout({ type, functionName, timeoutMs }, restartRuntime);
88611
88658
  const error = new Error(
88612
88659
  `Function "${functionName}" exceeded ${timeoutMs / 1e3}s time limit. Split into smaller mutations and call them sequentially from the frontend. Limits: query 30s, mutation 30s, httpAction 5min, cron 10min.`
@@ -88616,6 +88663,22 @@ async function executeWithTimeout(fn, type, functionName, timeouts = FUNCTION_TI
88616
88663
  });
88617
88664
  })
88618
88665
  ]);
88666
+ const elapsedMs = Date.now() - startedAt;
88667
+ if (slowLogMs > 0 && elapsedMs >= slowLogMs) {
88668
+ logger2.warn(
88669
+ `[runtime] function slow id=${invocationId} type=${type} name="${functionName}" elapsedMs=${elapsedMs} thresholdMs=${slowLogMs}`
88670
+ );
88671
+ }
88672
+ return result2;
88673
+ } catch (error) {
88674
+ const elapsedMs = Date.now() - startedAt;
88675
+ const code = error?.code;
88676
+ if (code !== "FUNCTION_TIMEOUT" && slowLogMs > 0 && elapsedMs >= slowLogMs) {
88677
+ logger2.warn(
88678
+ `[runtime] function slow failed id=${invocationId} type=${type} name="${functionName}" elapsedMs=${elapsedMs} thresholdMs=${slowLogMs} ${formatErrorForRuntimeLog(error)}`
88679
+ );
88680
+ }
88681
+ throw error;
88619
88682
  } finally {
88620
88683
  clearTimeout(timer);
88621
88684
  }