@open-mercato/core 0.10.1-develop.7708.1.5a5c248637 → 0.10.1-develop.7709.1.046124599c

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.
@@ -170,7 +170,7 @@ async function enqueueActivity(em, activity, context) {
170
170
  workflowContext,
171
171
  stepContext,
172
172
  retryPolicy: activity.retryPolicy,
173
- timeoutMs: activity.timeoutMs,
173
+ timeoutMs: resolveActivityTimeoutMs(activity),
174
174
  tenantId: workflowInstance.tenantId,
175
175
  organizationId: workflowInstance.organizationId,
176
176
  userId: context.userId
@@ -458,7 +458,8 @@ async function executeActivityByType(em, container, activity, context, signal) {
458
458
  return await entry.execute(interpolatedConfig, context, {
459
459
  em,
460
460
  container,
461
- signal
461
+ signal,
462
+ timeoutMs: resolveActivityTimeoutMs(activity)
462
463
  });
463
464
  }
464
465
  async function executeSendEmail(config, context, container, signal) {
@@ -669,6 +670,34 @@ async function resolveDictionaryEntryId(em, dictionaryKey, value, tenantId, orga
669
670
  return null;
670
671
  }
671
672
  }
673
+ const WEBHOOK_TIMEOUT_MS = 3e4;
674
+ const WEBHOOK_MAX_RESPONSE_BYTES = 1024 * 1024;
675
+ async function readWebhookResponse(response, signal) {
676
+ const declaredLength = Number(response.headers.get("content-length"));
677
+ if (declaredLength > WEBHOOK_MAX_RESPONSE_BYTES) {
678
+ throw new Error(`[internal] CALL_WEBHOOK response exceeds ${WEBHOOK_MAX_RESPONSE_BYTES} bytes`);
679
+ }
680
+ if (!response.body) return "";
681
+ const reader = response.body.getReader();
682
+ const chunks = [];
683
+ let totalBytes = 0;
684
+ try {
685
+ for (; ; ) {
686
+ throwIfAborted(signal);
687
+ const { done, value } = await raceAbortable(reader.read(), signal);
688
+ if (done) break;
689
+ totalBytes += value.byteLength;
690
+ if (totalBytes > WEBHOOK_MAX_RESPONSE_BYTES) {
691
+ throw new Error(`[internal] CALL_WEBHOOK response exceeds ${WEBHOOK_MAX_RESPONSE_BYTES} bytes`);
692
+ }
693
+ chunks.push(value);
694
+ }
695
+ return new TextDecoder().decode(Buffer.concat(chunks, totalBytes));
696
+ } finally {
697
+ void reader.cancel().catch(() => void 0);
698
+ reader.releaseLock();
699
+ }
700
+ }
672
701
  async function executeCallWebhook(config, context, deps = {}) {
673
702
  const parsed = callWebhookConfigSchema.safeParse(config);
674
703
  if (!parsed.success) {
@@ -678,58 +707,56 @@ async function executeCallWebhook(config, context, deps = {}) {
678
707
  const { url, method, headers: rawHeaders, body } = parsed.data;
679
708
  const headers = rawHeaders ?? {};
680
709
  const allowPrivate = deps.allowPrivate ?? isAllowPrivateWorkflowWebhookUrlsEnabled();
681
- let response;
682
- try {
683
- response = await safeOutboundFetch(
684
- url,
685
- {
686
- method,
687
- headers: {
688
- "Content-Type": "application/json",
689
- ...headers
710
+ return executeWithTimeout(async (deadlineSignal) => {
711
+ const signal = deps.signal ? AbortSignal.any([deadlineSignal, deps.signal]) : deadlineSignal;
712
+ throwIfAborted(signal);
713
+ let response;
714
+ try {
715
+ response = await raceAbortable(safeOutboundFetch(
716
+ url,
717
+ {
718
+ method,
719
+ headers: {
720
+ "Content-Type": "application/json",
721
+ ...headers
722
+ },
723
+ body: body !== void 0 && body !== null ? JSON.stringify(body) : void 0,
724
+ redirect: "manual",
725
+ signal
690
726
  },
691
- body: body !== void 0 && body !== null ? JSON.stringify(body) : void 0,
692
- redirect: "manual",
693
- signal: deps.signal
694
- },
695
- {
696
- subject: "Workflow webhook URL",
697
- allowPrivate,
698
- lookupHost: deps.lookupHost,
699
- fetchImpl: deps.fetchImpl
727
+ {
728
+ subject: "Workflow webhook URL",
729
+ allowPrivate,
730
+ lookupHost: deps.lookupHost,
731
+ fetchImpl: deps.fetchImpl
732
+ }
733
+ ), signal);
734
+ if (response.status >= 300 && response.status < 400) {
735
+ const location = response.headers.get("location");
736
+ throw new Error(
737
+ `CALL_WEBHOOK refused to follow redirect ${response.status} to ${location ?? "(no Location header)"}`
738
+ );
700
739
  }
701
- );
702
- } catch (error) {
703
- if (error instanceof UnsafeOutboundUrlError) {
704
- throw new Error(
705
- `CALL_WEBHOOK rejected unsafe URL (reason=${error.reason}): ${error.message}`
706
- );
740
+ const text = await readWebhookResponse(response, signal);
741
+ const contentType = response.headers.get("content-type");
742
+ const result = contentType?.includes("application/json") ? JSON.parse(text) : text;
743
+ if (!response.ok) {
744
+ throw new Error(
745
+ `Webhook request failed with status ${response.status}: ${JSON.stringify(result)}`
746
+ );
747
+ }
748
+ return { status: response.status, statusText: response.statusText, result };
749
+ } catch (error) {
750
+ if (error instanceof UnsafeOutboundUrlError) {
751
+ throw new Error(
752
+ `CALL_WEBHOOK rejected unsafe URL (reason=${error.reason}): ${error.message}`
753
+ );
754
+ }
755
+ throw error;
756
+ } finally {
757
+ void response?.body?.cancel().catch(() => void 0);
707
758
  }
708
- throw error;
709
- }
710
- if (response.status >= 300 && response.status < 400) {
711
- const location = response.headers.get("location");
712
- throw new Error(
713
- `CALL_WEBHOOK refused to follow redirect ${response.status} to ${location ?? "(no Location header)"}`
714
- );
715
- }
716
- let result;
717
- const contentType = response.headers.get("content-type");
718
- if (contentType && contentType.includes("application/json")) {
719
- result = await response.json();
720
- } else {
721
- result = await response.text();
722
- }
723
- if (!response.ok) {
724
- throw new Error(
725
- `Webhook request failed with status ${response.status}: ${JSON.stringify(result)}`
726
- );
727
- }
728
- return {
729
- status: response.status,
730
- statusText: response.statusText,
731
- result
732
- };
759
+ }, deps.timeoutMs && deps.timeoutMs > 0 ? deps.timeoutMs : WEBHOOK_TIMEOUT_MS);
733
760
  }
734
761
  async function executeFunction(config, context, container, signal) {
735
762
  const { functionName, args = {} } = config;