dataiku-sdk 3.8.0 → 4.0.0
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/README.md +7 -5
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +4 -0
- package/dist/packages/types/src/index.js +4 -0
- package/dist/src/cli/coerce.d.ts +6 -0
- package/dist/src/cli/coerce.js +9 -0
- package/dist/src/cli/command-syntax.json +36 -0
- package/dist/src/cli/commands/app.js +2 -2
- package/dist/src/cli/commands/code-env.js +5 -6
- package/dist/src/cli/commands/code.js +16 -2
- package/dist/src/cli/commands/dashboard.js +1 -2
- package/dist/src/cli/commands/dataset.js +2 -2
- package/dist/src/cli/commands/flow-zone.js +1 -1
- package/dist/src/cli/commands/job.js +101 -22
- package/dist/src/cli/commands/plugin.js +7 -7
- package/dist/src/cli/commands/project-library.js +2 -2
- package/dist/src/cli/commands/project.js +25 -7
- package/dist/src/cli/commands/recipe.js +11 -19
- package/dist/src/cli/commands/scenario.js +2 -4
- package/dist/src/cli/contract.js +29 -10
- package/dist/src/cli/env.js +2 -3
- package/dist/src/cli/helpers/app-permissions.d.ts +1 -1
- package/dist/src/cli/helpers/app-permissions.js +2 -2
- package/dist/src/cli/helpers/cleanup.d.ts +2 -0
- package/dist/src/cli/helpers/cleanup.js +122 -8
- package/dist/src/cli/helpers/flow-zone.d.ts +1 -1
- package/dist/src/cli/helpers/flow-zone.js +3 -4
- package/dist/src/cli/list-output.d.ts +5 -0
- package/dist/src/cli/list-output.js +11 -2
- package/dist/src/cli/list-shapes.d.ts +6 -0
- package/dist/src/cli/list-shapes.js +7 -1
- package/dist/src/cli/output-schemas.d.ts +1 -1
- package/dist/src/cli/output-schemas.js +28 -4
- package/dist/src/cli/output.js +7 -0
- package/dist/src/cli/project-map-output.d.ts +24 -0
- package/dist/src/cli/project-map-output.js +21 -0
- package/dist/src/cli/read-shapes.d.ts +14 -0
- package/dist/src/cli/read-shapes.js +114 -0
- package/dist/src/cli/result-shapes.d.ts +6 -0
- package/dist/src/cli/result-shapes.js +235 -0
- package/dist/src/cli/version.d.ts +2 -2
- package/dist/src/cli/version.js +4 -5
- package/dist/src/cli.js +77 -33
- package/dist/src/client.d.ts +14 -2
- package/dist/src/client.js +18 -10
- package/dist/src/generated/action-output-schemas.json +242 -35
- package/dist/src/index.d.ts +1 -1
- package/dist/src/resources/datasets.d.ts +11 -1
- package/dist/src/resources/datasets.js +91 -30
- package/dist/src/resources/jobs.d.ts +37 -6
- package/dist/src/resources/jobs.js +110 -44
- package/dist/src/resources/projects.js +2 -2
- package/dist/src/resources/recipes.d.ts +12 -1
- package/dist/src/resources/recipes.js +39 -12
- package/dist/src/resources/scenarios.d.ts +8 -1
- package/dist/src/resources/scenarios.js +51 -12
- package/dist/src/resources/wiki.js +3 -7
- package/dist/src/skill.js +1 -2
- package/dist/src/utils/project-archive.d.ts +25 -0
- package/dist/src/utils/project-archive.js +216 -5
- package/dist/src/utils/response-file.js +15 -8
- package/dist/src/utils/secret-sanitize.d.ts +11 -2
- package/dist/src/utils/secret-sanitize.js +23 -6
- package/package.json +13 -14
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +1 -1
- package/skills/dataiku-dss/references/discovery.md +2 -2
- package/skills/dataiku-dss/references/troubleshooting.md +2 -2
package/dist/src/cli.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import * as fs from "node:fs/promises";
|
|
3
2
|
import { homedir, } from "node:os";
|
|
4
3
|
import { resolve, } from "node:path";
|
|
5
|
-
import { num, seenJsonInputCredentials, unknownJsonInput, } from "./cli/coerce.js";
|
|
4
|
+
import { num, resultRecord, seenJsonInputCredentials, stringField, unknownJsonInput, } from "./cli/coerce.js";
|
|
6
5
|
import { commands, } from "./cli/commands/index.js";
|
|
7
6
|
import { ambientProjectKey, loadEnvFile, } from "./cli/env.js";
|
|
8
7
|
import { executionMode, FLAG_ALIASES, isFlagValueToken, parseArgs, rawPositionals, } from "./cli/flags.js";
|
|
9
|
-
import { cleanupLedgerEntry, } from "./cli/helpers/cleanup.js";
|
|
10
|
-
import { shapeListResult, } from "./cli/list-output.js";
|
|
8
|
+
import { cleanupInputIdentifierField, cleanupLedgerEntry, } from "./cli/helpers/cleanup.js";
|
|
11
9
|
import { commandFailureExitCode, CommandResultFailure, enqueueCliWarning, flushCliWarnings, isFailedWaitResult, planResult, projectResultFields, setOutputFieldProjection, writeCommandResult, } from "./cli/output.js";
|
|
10
|
+
import { shapeCommandResult, } from "./cli/result-shapes.js";
|
|
12
11
|
import { currentCommandContext, resolveCredentials, resolveLoginCredentials, } from "./cli/runtime.js";
|
|
13
12
|
import { commandSyntaxTree, commandUsage, } from "./cli/syntax.js";
|
|
14
13
|
import { COMMANDS_RUN_HINT, inferRequiresProject, missingActionError, noCommandError, requireArgs, RESOURCE_NAMES, unknownActionError, unknownFlagError, unknownResourceError, UsageError, } from "./cli/usage.js";
|
|
@@ -786,7 +785,7 @@ async function commandsRunResult(flags) {
|
|
|
786
785
|
: projectResultFields(registry, selectors, () => Object.keys(contract.commandActionSummary()).sort());
|
|
787
786
|
if (typeof outputPath === "string") {
|
|
788
787
|
const exported = selectedRegistry;
|
|
789
|
-
await
|
|
788
|
+
await Bun.write(outputPath, `${JSON.stringify(exported)}\n`);
|
|
790
789
|
return { path: outputPath, };
|
|
791
790
|
}
|
|
792
791
|
return selectedRegistry;
|
|
@@ -802,8 +801,9 @@ function assertCleanupLedgerSupported(resource, action, flags) {
|
|
|
802
801
|
if (!contract.supportsCleanupLedger(resource, action)) {
|
|
803
802
|
throw new UsageError(`--record-cleanup is not supported for ${resource} ${action}.`);
|
|
804
803
|
}
|
|
805
|
-
|
|
806
|
-
|
|
804
|
+
const pinnedField = cleanupInputIdentifierField(resource, action);
|
|
805
|
+
if (pinnedField !== undefined && flags["stdin"] === true) {
|
|
806
|
+
throw new UsageError(`${resource} ${action} cannot combine --record-cleanup with --stdin because the cleanup identifier cannot be replayed from a consumed stream.`, "conflicting_input_sources", `Use --data or --data-file so the ${pinnedField} remains available for the cleanup ledger.`);
|
|
807
807
|
}
|
|
808
808
|
}
|
|
809
809
|
/**
|
|
@@ -856,11 +856,36 @@ async function preflightCleanupLedgerForFlags(client, flags) {
|
|
|
856
856
|
}
|
|
857
857
|
}
|
|
858
858
|
/**
|
|
859
|
-
*
|
|
860
|
-
*
|
|
861
|
-
*
|
|
862
|
-
*
|
|
863
|
-
|
|
859
|
+
* What the command result already says about the created object, so a failed
|
|
860
|
+
* ledger write never hides it: the `created`/`saved` receipt, the object `id`
|
|
861
|
+
* and `name`, and the project key DSS landed it in. Fields stay distinct (a
|
|
862
|
+
* name is not an id) and absent ones are omitted rather than guessed.
|
|
863
|
+
*/
|
|
864
|
+
function createdObjectFromResult(result, fallbackProjectKey) {
|
|
865
|
+
const record = resultRecord(result);
|
|
866
|
+
const created = stringField(record, ["created", "saved", "usedProjectKey",]);
|
|
867
|
+
const id = stringField(record, ["id",]);
|
|
868
|
+
const name = stringField(record, ["name",]);
|
|
869
|
+
const projectKey = stringField(record, ["projectKey", "usedProjectKey", "targetProjectKey",])
|
|
870
|
+
?? fallbackProjectKey;
|
|
871
|
+
return {
|
|
872
|
+
...(created ? { created, } : {}),
|
|
873
|
+
...(id ? { id, } : {}),
|
|
874
|
+
...(name ? { name, } : {}),
|
|
875
|
+
...(projectKey ? { projectKey, } : {}),
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Append the cleanup entry for a completed handler result. Callers must call
|
|
880
|
+
* this before any failure exit code is raised: an indeterminate post-POST
|
|
881
|
+
* outcome stays addressable only when the ledger records it first. Eligibility
|
|
882
|
+
* (dry runs, skipped work, an explicit `cleanupEligible:false`) is decided by
|
|
883
|
+
* `cleanupLedgerEntry`, never here.
|
|
884
|
+
*
|
|
885
|
+
* The mutation has already happened when this runs, so every failure here is
|
|
886
|
+
* an `ambiguous_outcome` that says so (`mutationSucceeded: true`,
|
|
887
|
+
* `cleanupRecorded: false`) and carries the created identifier/project key:
|
|
888
|
+
* callers must never retry the create, only clean up or record it themselves.
|
|
864
889
|
*/
|
|
865
890
|
async function recordCleanupLedgerEntry(client, resource, action, args, flags, result, projectKey) {
|
|
866
891
|
const ledgerPath = flags["record-cleanup"];
|
|
@@ -868,15 +893,33 @@ async function recordCleanupLedgerEntry(client, resource, action, args, flags, r
|
|
|
868
893
|
return;
|
|
869
894
|
const entry = cleanupLedgerEntry(resource, action, args, flags, result, projectKey);
|
|
870
895
|
if (entry) {
|
|
871
|
-
|
|
896
|
+
try {
|
|
897
|
+
await appendCleanupLedgerEntry(ledgerPath, entry, client.getBaseUrl());
|
|
898
|
+
}
|
|
899
|
+
catch (error) {
|
|
900
|
+
throw new ClientValidationError(`Mutation completed but the cleanup entry for ${resource} ${action} could not be recorded: ${error instanceof Error ? error.message : String(error)}`, "ambiguous_outcome", "The mutation already succeeded: do not retry it. Remove the created object manually or append this cleanup entry to the ledger yourself.", {
|
|
901
|
+
resource,
|
|
902
|
+
action,
|
|
903
|
+
ledgerPath,
|
|
904
|
+
mutationSucceeded: true,
|
|
905
|
+
cleanupRecorded: false,
|
|
906
|
+
...createdObjectFromResult(result, projectKey),
|
|
907
|
+
cleanup: entry.cleanup,
|
|
908
|
+
});
|
|
909
|
+
}
|
|
872
910
|
return;
|
|
873
911
|
}
|
|
874
|
-
const record =
|
|
875
|
-
? result
|
|
876
|
-
: {};
|
|
912
|
+
const record = resultRecord(result);
|
|
877
913
|
if (record.skipped !== undefined || record.cleanupEligible === false)
|
|
878
914
|
return;
|
|
879
|
-
throw new ClientValidationError(`Mutation completed but no cleanup entry could be derived for ${resource} ${action}.`, "ambiguous_outcome", "Inspect the created object and remove it manually;
|
|
915
|
+
throw new ClientValidationError(`Mutation completed but no cleanup entry could be derived for ${resource} ${action}.`, "ambiguous_outcome", "The mutation already succeeded: do not retry it. Inspect the created object and remove it manually; the requested cleanup ledger does not contain it.", {
|
|
916
|
+
resource,
|
|
917
|
+
action,
|
|
918
|
+
ledgerPath,
|
|
919
|
+
mutationSucceeded: true,
|
|
920
|
+
cleanupRecorded: false,
|
|
921
|
+
...createdObjectFromResult(result, projectKey),
|
|
922
|
+
});
|
|
880
923
|
}
|
|
881
924
|
async function runBatch(flags) {
|
|
882
925
|
const payload = unknownJsonInput(flags);
|
|
@@ -1022,8 +1065,7 @@ async function runBatch(flags) {
|
|
|
1022
1065
|
await preflightCleanupLedgerForFlags(client, stepFlags);
|
|
1023
1066
|
const stepArgs = positional.slice(2);
|
|
1024
1067
|
result = await meta.handler(client, stepArgs, stepFlags);
|
|
1025
|
-
|
|
1026
|
-
result = shapeListResult(resource, result, stepFlags);
|
|
1068
|
+
result = shapeCommandResult(resource, action, result, stepFlags);
|
|
1027
1069
|
await recordCleanupLedgerEntry(client, resource, action, stepArgs, stepFlags, result, projectKey);
|
|
1028
1070
|
}
|
|
1029
1071
|
const failureExitCode = commandFailureExitCode(result);
|
|
@@ -1301,27 +1343,33 @@ function errorExitCode(err) {
|
|
|
1301
1343
|
}
|
|
1302
1344
|
function buildErrorReport(err, contextOverride) {
|
|
1303
1345
|
const context = contextOverride ?? rawCommandContext();
|
|
1346
|
+
// The envelope echoes only the resolved project; resource/action are known to the caller.
|
|
1347
|
+
const scope = context.projectKey ? { projectKey: context.projectKey, } : {};
|
|
1304
1348
|
const exitCode = errorExitCode(err);
|
|
1305
1349
|
if (err instanceof ClientValidationError
|
|
1306
1350
|
&& (err.code === "ambiguous_outcome" || err.code === "assertion_failed"
|
|
1307
1351
|
|| err.code === "long_running_failure")) {
|
|
1352
|
+
// The DSS response behind an indeterminate outcome stays visible (status,
|
|
1353
|
+
// sanitized message), e.g. a 500 that names the conflicting project key.
|
|
1354
|
+
const cause = err.cause instanceof DataikuError ? err.cause : undefined;
|
|
1355
|
+
const diagnostics = cause ? dssDiagnosticDetails(cause) : {};
|
|
1356
|
+
const details = { ...diagnostics, ...err.details, };
|
|
1308
1357
|
return {
|
|
1309
1358
|
type: "error",
|
|
1310
|
-
ok: false,
|
|
1311
1359
|
error: err.message,
|
|
1312
1360
|
code: err.code,
|
|
1313
1361
|
category: "dss",
|
|
1314
1362
|
exitCode,
|
|
1363
|
+
...(cause ? { status: cause.status, } : {}),
|
|
1315
1364
|
retryable: false,
|
|
1316
1365
|
...(err.hint ? { hint: err.hint, } : {}),
|
|
1317
|
-
...(
|
|
1318
|
-
...
|
|
1366
|
+
...(Object.keys(details).length > 0 ? { details, } : {}),
|
|
1367
|
+
...scope,
|
|
1319
1368
|
};
|
|
1320
1369
|
}
|
|
1321
1370
|
if (err instanceof UsageError || err instanceof ClientValidationError) {
|
|
1322
1371
|
return {
|
|
1323
1372
|
type: "error",
|
|
1324
|
-
ok: false,
|
|
1325
1373
|
error: err.message,
|
|
1326
1374
|
code: err.code,
|
|
1327
1375
|
category: err.code === "target_absence_unverifiable"
|
|
@@ -1333,26 +1381,24 @@ function buildErrorReport(err, contextOverride) {
|
|
|
1333
1381
|
...(err.code === "target_absence_unverifiable" ? { retryable: false, } : {}),
|
|
1334
1382
|
...(err.hint ? { hint: err.hint, } : {}),
|
|
1335
1383
|
...(err.details ? { details: err.details, } : {}),
|
|
1336
|
-
...
|
|
1384
|
+
...scope,
|
|
1337
1385
|
};
|
|
1338
1386
|
}
|
|
1339
1387
|
if (err instanceof CommandResultFailure) {
|
|
1340
1388
|
return {
|
|
1341
1389
|
type: "error",
|
|
1342
|
-
ok: false,
|
|
1343
1390
|
error: err.message,
|
|
1344
1391
|
code: err.code,
|
|
1345
1392
|
category: "dss",
|
|
1346
1393
|
exitCode: err.exitCode,
|
|
1347
1394
|
details: boundedFailureResult(err.result),
|
|
1348
|
-
...
|
|
1395
|
+
...scope,
|
|
1349
1396
|
};
|
|
1350
1397
|
}
|
|
1351
1398
|
if (isAmbiguousMutationFailure(err, context)) {
|
|
1352
1399
|
const method = err.retry?.method.toUpperCase() ?? "mutation";
|
|
1353
1400
|
return {
|
|
1354
1401
|
type: "error",
|
|
1355
|
-
ok: false,
|
|
1356
1402
|
error: `The ${method} request failed after dispatch; the mutation outcome is unknown.`,
|
|
1357
1403
|
code: "ambiguous_outcome",
|
|
1358
1404
|
category: "dss",
|
|
@@ -1369,7 +1415,7 @@ function buildErrorReport(err, contextOverride) {
|
|
|
1369
1415
|
...err.details,
|
|
1370
1416
|
...(err.retry ? { retry: err.retry, } : {}),
|
|
1371
1417
|
},
|
|
1372
|
-
...
|
|
1418
|
+
...scope,
|
|
1373
1419
|
};
|
|
1374
1420
|
}
|
|
1375
1421
|
if (err instanceof DataikuError) {
|
|
@@ -1391,7 +1437,6 @@ function buildErrorReport(err, contextOverride) {
|
|
|
1391
1437
|
: err.retryHint;
|
|
1392
1438
|
return {
|
|
1393
1439
|
type: "error",
|
|
1394
|
-
ok: false,
|
|
1395
1440
|
error: dssMessage ? `${err.safeMessage}: ${dssMessage}` : err.safeMessage,
|
|
1396
1441
|
code: dataikuErrorCode(err.category),
|
|
1397
1442
|
category: "dss",
|
|
@@ -1401,18 +1446,17 @@ function buildErrorReport(err, contextOverride) {
|
|
|
1401
1446
|
retryable: err.retryable,
|
|
1402
1447
|
requestId: err.requestId ?? requestIdFromBody(err.body),
|
|
1403
1448
|
...(Object.keys(details).length > 0 ? { details, } : {}),
|
|
1404
|
-
...
|
|
1449
|
+
...scope,
|
|
1405
1450
|
};
|
|
1406
1451
|
}
|
|
1407
1452
|
const message = err instanceof Error ? err.message : String(err);
|
|
1408
1453
|
return {
|
|
1409
1454
|
type: "error",
|
|
1410
|
-
ok: false,
|
|
1411
1455
|
error: message,
|
|
1412
1456
|
code: "internal_error",
|
|
1413
1457
|
category: "internal",
|
|
1414
1458
|
exitCode,
|
|
1415
|
-
...
|
|
1459
|
+
...scope,
|
|
1416
1460
|
};
|
|
1417
1461
|
}
|
|
1418
1462
|
function writeErrorReport(err) {
|
|
@@ -1524,7 +1568,7 @@ async function main() {
|
|
|
1524
1568
|
assertCleanupLedgerSupported(resource, action, flags);
|
|
1525
1569
|
await preflightCleanupLedgerForFlags(client, flags);
|
|
1526
1570
|
const handled = await actionMeta.handler(client, args, flags);
|
|
1527
|
-
const result =
|
|
1571
|
+
const result = shapeCommandResult(resource, action, handled, flags);
|
|
1528
1572
|
await recordCleanupLedgerEntry(client, resource, action, args, flags, result, projectKey);
|
|
1529
1573
|
const failureExitCode = commandFailureExitCode(result);
|
|
1530
1574
|
if (failureExitCode !== undefined)
|
package/dist/src/client.d.ts
CHANGED
|
@@ -153,7 +153,13 @@ export declare class DataikuClient {
|
|
|
153
153
|
private readonly maxResponseBodyBytes;
|
|
154
154
|
private readonly retryMaxAttempts;
|
|
155
155
|
private readonly verbose;
|
|
156
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Connection pool carrying this client's TLS settings (custom CA, disabled
|
|
158
|
+
* verification). A session never shares connections with plain `fetch` or
|
|
159
|
+
* another client, so a connection opened with relaxed TLS cannot serve a
|
|
160
|
+
* client that expects strict verification. Default-TLS clients use plain fetch.
|
|
161
|
+
*/
|
|
162
|
+
private readonly session;
|
|
157
163
|
private readonly onTrace;
|
|
158
164
|
private readonly onValidationWarning;
|
|
159
165
|
private projectsResource?;
|
|
@@ -294,7 +300,8 @@ export declare class DataikuClient {
|
|
|
294
300
|
* When the response exceeds the cap, earlier bytes are discarded, only
|
|
295
301
|
* the tail is kept and `truncated` is true — so callers that need the end
|
|
296
302
|
* of a large document (e.g. job logs) stay bounded without losing the most
|
|
297
|
-
* recent content. The
|
|
303
|
+
* recent content. The request timeout applies per received chunk (a stall
|
|
304
|
+
* deadline), not to the whole transfer.
|
|
298
305
|
*/
|
|
299
306
|
getTextTailLimited(path: string, maxBytes: number): Promise<{
|
|
300
307
|
text: string;
|
|
@@ -385,6 +392,11 @@ export declare class DataikuClient {
|
|
|
385
392
|
* Returns `truncated: true` when bytes had to be dropped. Bytes that fall
|
|
386
393
|
* in the middle of a UTF-8 character are dropped from both ends so the
|
|
387
394
|
* decoded text never contains a replacement character.
|
|
395
|
+
*
|
|
396
|
+
* The request timeout applies per chunk (a stall deadline), like the
|
|
397
|
+
* streaming path: a large body that keeps arriving is read to EOF however
|
|
398
|
+
* long the whole transfer takes, while a body that stops sending for longer
|
|
399
|
+
* than the timeout fails with the body-read timeout error.
|
|
388
400
|
*/
|
|
389
401
|
private readBodyTextTail;
|
|
390
402
|
private buildResponseTooLargeError;
|
package/dist/src/client.js
CHANGED
|
@@ -211,7 +211,13 @@ export class DataikuClient {
|
|
|
211
211
|
maxResponseBodyBytes;
|
|
212
212
|
retryMaxAttempts;
|
|
213
213
|
verbose;
|
|
214
|
-
|
|
214
|
+
/**
|
|
215
|
+
* Connection pool carrying this client's TLS settings (custom CA, disabled
|
|
216
|
+
* verification). A session never shares connections with plain `fetch` or
|
|
217
|
+
* another client, so a connection opened with relaxed TLS cannot serve a
|
|
218
|
+
* client that expects strict verification. Default-TLS clients use plain fetch.
|
|
219
|
+
*/
|
|
220
|
+
session;
|
|
215
221
|
onTrace;
|
|
216
222
|
onValidationWarning;
|
|
217
223
|
/* Resource namespaces — lazily initialized to break circular imports */
|
|
@@ -606,7 +612,8 @@ export class DataikuClient {
|
|
|
606
612
|
const rawMax = config?.retryMaxAttempts ?? DEFAULT_RETRY_MAX_ATTEMPTS;
|
|
607
613
|
this.retryMaxAttempts = Math.min(Math.max(1, rawMax), MAX_RETRY_ATTEMPTS_CAP);
|
|
608
614
|
this.verbose = config?.verbose === true;
|
|
609
|
-
|
|
615
|
+
const tls = config ? buildFetchTlsOptions(config) : undefined;
|
|
616
|
+
this.session = tls ? new Bun.FetchSession({ tls, }) : undefined;
|
|
610
617
|
this.onTrace = config?.onTrace ?? defaultTrace;
|
|
611
618
|
this.onValidationWarning = config?.onValidationWarning ?? defaultValidationWarning;
|
|
612
619
|
}
|
|
@@ -691,7 +698,8 @@ export class DataikuClient {
|
|
|
691
698
|
* When the response exceeds the cap, earlier bytes are discarded, only
|
|
692
699
|
* the tail is kept and `truncated` is true — so callers that need the end
|
|
693
700
|
* of a large document (e.g. job logs) stay bounded without losing the most
|
|
694
|
-
* recent content. The
|
|
701
|
+
* recent content. The request timeout applies per received chunk (a stall
|
|
702
|
+
* deadline), not to the whole transfer.
|
|
695
703
|
*/
|
|
696
704
|
async getTextTailLimited(path, maxBytes) {
|
|
697
705
|
const limit = Math.max(0, Math.floor(maxBytes));
|
|
@@ -1080,6 +1088,11 @@ export class DataikuClient {
|
|
|
1080
1088
|
* Returns `truncated: true` when bytes had to be dropped. Bytes that fall
|
|
1081
1089
|
* in the middle of a UTF-8 character are dropped from both ends so the
|
|
1082
1090
|
* decoded text never contains a replacement character.
|
|
1091
|
+
*
|
|
1092
|
+
* The request timeout applies per chunk (a stall deadline), like the
|
|
1093
|
+
* streaming path: a large body that keeps arriving is read to EOF however
|
|
1094
|
+
* long the whole transfer takes, while a body that stops sending for longer
|
|
1095
|
+
* than the timeout fails with the body-read timeout error.
|
|
1083
1096
|
*/
|
|
1084
1097
|
async readBodyTextTail(res, maxBytes) {
|
|
1085
1098
|
const limit = Math.max(0, Math.floor(maxBytes));
|
|
@@ -1090,13 +1103,9 @@ export class DataikuClient {
|
|
|
1090
1103
|
let writeOffset = 0;
|
|
1091
1104
|
let retainedBytes = 0;
|
|
1092
1105
|
let truncated = false;
|
|
1093
|
-
const startedAt = Date.now();
|
|
1094
1106
|
try {
|
|
1095
1107
|
while (true) {
|
|
1096
|
-
const
|
|
1097
|
-
if (remainingMs <= 0)
|
|
1098
|
-
throw buildBodyReadTimeoutError(this.requestTimeoutMs);
|
|
1099
|
-
const { done, value, } = await readChunkWithDeadline(reader, remainingMs, this.requestTimeoutMs);
|
|
1108
|
+
const { done, value, } = await readChunkWithDeadline(reader, this.requestTimeoutMs, this.requestTimeoutMs);
|
|
1100
1109
|
if (done)
|
|
1101
1110
|
break;
|
|
1102
1111
|
if (limit === 0) {
|
|
@@ -1187,9 +1196,8 @@ export class DataikuClient {
|
|
|
1187
1196
|
...init,
|
|
1188
1197
|
method,
|
|
1189
1198
|
signal: controller.signal,
|
|
1199
|
+
...(this.session ? { session: this.session, } : {}),
|
|
1190
1200
|
};
|
|
1191
|
-
if (this.tlsOptions)
|
|
1192
|
-
requestInit.tls = this.tlsOptions;
|
|
1193
1201
|
const res = await fetch(url, requestInit);
|
|
1194
1202
|
this.logTrace({
|
|
1195
1203
|
phase: "response",
|