@microsoft/rayfin-functions 1.35.0-alpha.1331 → 1.35.0-alpha.1374

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.
@@ -31,6 +31,21 @@ export interface FunctionInvocationResponse<TOutput = any> {
31
31
  export interface InvokeOptions {
32
32
  /** Extra headers to attach to the request. */
33
33
  headers?: Record<string, string>;
34
+ /**
35
+ * Per-call request timeout in milliseconds, overriding the default function
36
+ * invocation timeout (`FUNCTIONS_INVOKE_TIMEOUT_MS`, 250s). Use this
37
+ * for functions that should fail faster than the default.
38
+ *
39
+ * Capped at `FUNCTIONS_INVOKE_TIMEOUT_MS` (250s): the Fabric UDF host
40
+ * aborts the invocation at that ceiling server-side, so a larger value is
41
+ * silently clamped down. A non-positive value falls back to the default.
42
+ *
43
+ * For a no-input function, pass options in the second argument slot
44
+ * (`invoke(undefined, { timeoutMs })`) rather than as the single
45
+ * argument, so the option is never confused with a function's own input.
46
+ * See the note on {@link FunctionClient.invoke}.
47
+ */
48
+ timeoutMs?: number;
34
49
  }
35
50
  /**
36
51
  * A strongly-typed client for a single function.
@@ -45,11 +60,17 @@ export declare class FunctionClient<TInput = any, TOutput = any> {
45
60
  /**
46
61
  * Invoke the function and return its typed output.
47
62
  *
48
- * @param args - When the function accepts input, pass
49
- * `[params, options?]` `params` are the input parameters declared
50
- * by the function schema, `options` are optional per-call settings
51
- * (extra headers, etc.). When the function takes no input, pass
52
- * `[options?]` instead.
63
+ * @param args - Options always go in the **second** argument slot; the
64
+ * first argument is always the function's input `params`.
65
+ *
66
+ * - Input functions: `invoke(params)` or `invoke(params, options)`.
67
+ * - No-input functions: `invoke()` or `invoke(undefined, options)`.
68
+ *
69
+ * A lone argument is therefore always treated as `params`, never as
70
+ * options — so a real input that happens to be shaped like an option
71
+ * (for example `{ timeoutMs }`) is never misread. For a no-input function
72
+ * the type forbids a lone object, so per-call options such as `timeoutMs`
73
+ * must be passed in the second slot (`invoke(undefined, { timeoutMs })`).
53
74
  * @returns The function's success-path output, typed as `TOutput`.
54
75
  *
55
76
  * Failure modes throw — a non-empty `errors` array or a non-success
@@ -75,8 +96,14 @@ export declare class FunctionClient<TInput = any, TOutput = any> {
75
96
  * lastName: 'Lovelace',
76
97
  * });
77
98
  * console.log(greeting); // typed as string
99
+ *
100
+ * // Per-call timeout override (input function):
101
+ * await client.functions.longRunning.invoke(params, { timeoutMs: 5_000 });
102
+ *
103
+ * // No-input function with a per-call timeout override (second slot):
104
+ * await client.functions.ping.invoke(undefined, { timeoutMs: 5_000 });
78
105
  * ```
79
106
  */
80
- invoke(...args: TInput extends void | Record<string, never> ? [options?: InvokeOptions] : [params: TInput, options?: InvokeOptions]): Promise<TOutput>;
107
+ invoke(...args: TInput extends void | Record<string, never> ? [params?: undefined, options?: InvokeOptions] : [params: TInput, options?: InvokeOptions]): Promise<TOutput>;
81
108
  }
82
109
  //# sourceMappingURL=FunctionClient.d.ts.map
@@ -6,8 +6,24 @@
6
6
  * entry for that function name.
7
7
  */
8
8
  import { SdkError, NetworkError } from '@microsoft/rayfin-lib';
9
- import { FUNCTIONS_BASE_PATH } from '@microsoft/rayfin-lib';
9
+ import { FUNCTIONS_BASE_PATH, FUNCTIONS_INVOKE_TIMEOUT_MS, } from '@microsoft/rayfin-lib';
10
10
  import { FunctionsError } from './Functions.js';
11
+ /**
12
+ * Resolve the effective request timeout for an invocation.
13
+ *
14
+ * The Fabric UDF host aborts an invocation at `FUNCTIONS_INVOKE_TIMEOUT_MS`
15
+ * (250s), so a per-call override larger than that can never take effect — it is
16
+ * clamped down to the ceiling. A missing or non-positive override falls back to
17
+ * the default (a `0`/negative value would otherwise abort the request instantly).
18
+ */
19
+ function resolveInvokeTimeout(timeoutMs) {
20
+ if (typeof timeoutMs !== 'number' ||
21
+ !Number.isFinite(timeoutMs) ||
22
+ timeoutMs <= 0) {
23
+ return FUNCTIONS_INVOKE_TIMEOUT_MS;
24
+ }
25
+ return Math.min(timeoutMs, FUNCTIONS_INVOKE_TIMEOUT_MS);
26
+ }
11
27
  /**
12
28
  * A strongly-typed client for a single function.
13
29
  *
@@ -24,11 +40,17 @@ export class FunctionClient {
24
40
  /**
25
41
  * Invoke the function and return its typed output.
26
42
  *
27
- * @param args - When the function accepts input, pass
28
- * `[params, options?]` `params` are the input parameters declared
29
- * by the function schema, `options` are optional per-call settings
30
- * (extra headers, etc.). When the function takes no input, pass
31
- * `[options?]` instead.
43
+ * @param args - Options always go in the **second** argument slot; the
44
+ * first argument is always the function's input `params`.
45
+ *
46
+ * - Input functions: `invoke(params)` or `invoke(params, options)`.
47
+ * - No-input functions: `invoke()` or `invoke(undefined, options)`.
48
+ *
49
+ * A lone argument is therefore always treated as `params`, never as
50
+ * options — so a real input that happens to be shaped like an option
51
+ * (for example `{ timeoutMs }`) is never misread. For a no-input function
52
+ * the type forbids a lone object, so per-call options such as `timeoutMs`
53
+ * must be passed in the second slot (`invoke(undefined, { timeoutMs })`).
32
54
  * @returns The function's success-path output, typed as `TOutput`.
33
55
  *
34
56
  * Failure modes throw — a non-empty `errors` array or a non-success
@@ -54,33 +76,22 @@ export class FunctionClient {
54
76
  * lastName: 'Lovelace',
55
77
  * });
56
78
  * console.log(greeting); // typed as string
79
+ *
80
+ * // Per-call timeout override (input function):
81
+ * await client.functions.longRunning.invoke(params, { timeoutMs: 5_000 });
82
+ *
83
+ * // No-input function with a per-call timeout override (second slot):
84
+ * await client.functions.ping.invoke(undefined, { timeoutMs: 5_000 });
57
85
  * ```
58
86
  */
59
87
  async invoke(...args) {
60
88
  try {
61
- // Unpack the variadic args when TInput is void the first arg is options.
62
- let parameters;
63
- let options;
64
- if (args.length === 0) {
65
- // No-arg call: `fn.invoke()`
66
- }
67
- else if (args.length === 1) {
68
- // Could be `invoke(params)` or `invoke(options)` for void-input fns
69
- const first = args[0];
70
- if (first &&
71
- typeof first === 'object' &&
72
- 'headers' in first &&
73
- Object.keys(first).every((k) => k === 'headers')) {
74
- options = first;
75
- }
76
- else {
77
- parameters = first;
78
- }
79
- }
80
- else {
81
- parameters = args[0];
82
- options = args[1];
83
- }
89
+ // Options always live in the second slot; the first argument is always
90
+ // params (`undefined` for a no-input function). A lone argument is
91
+ // therefore never reinterpreted as options, so a real input shaped like
92
+ // `{ timeoutMs }` is sent verbatim — no key-sniffing needed.
93
+ const parameters = args[0];
94
+ const options = args[1];
84
95
  // When a `functionsBaseUrl` is configured on the ApiClient (e.g. by
85
96
  // local-debug flows that point at a `func start` process), invoke the
86
97
  // function directly against `${functionsBaseUrl}/api/<name>` using the
@@ -91,7 +102,14 @@ export class FunctionClient {
91
102
  const url = functionsBaseUrl
92
103
  ? `${functionsBaseUrl}/api/${this.functionName}`
93
104
  : `${FUNCTIONS_BASE_PATH}/${this.functionName}/invoke`;
94
- const response = await this.apiClient.post(url, parameters ?? {}, { headers: options?.headers });
105
+ const response = await this.apiClient.post(url, parameters ?? {}, {
106
+ headers: options?.headers,
107
+ // The server aborts a UDF invocation at FUNCTIONS_INVOKE_TIMEOUT_MS
108
+ // (250s), so a larger client timeout can never be honoured — clamp the
109
+ // per-call override to that ceiling. Non-positive values fall back to
110
+ // the default rather than timing out instantly.
111
+ timeout: resolveInvokeTimeout(options?.timeoutMs),
112
+ });
95
113
  // Check for errors in the response body
96
114
  if (response.errors && response.errors.length > 0) {
97
115
  const errorMessage = typeof response.errors[0] === 'string'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/rayfin-functions",
3
- "version": "1.35.0-alpha.1331",
3
+ "version": "1.35.0-alpha.1374",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -19,7 +19,7 @@
19
19
  "rimraf": "~6.0.1"
20
20
  },
21
21
  "dependencies": {
22
- "@microsoft/rayfin-lib": "1.35.0-alpha.1331"
22
+ "@microsoft/rayfin-lib": "1.35.0-alpha.1374"
23
23
  },
24
24
  "publishConfig": {
25
25
  "registry": "https://npm.pkg.github.com",