azure-kusto-ingest 4.0.5 → 5.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.
Files changed (57) hide show
  1. package/README.md +15 -2
  2. package/{source → dist-esm/src}/abstractKustoClient.js +0 -0
  3. package/{source → dist-esm/src}/columnMappings.js +0 -0
  4. package/dist-esm/src/descriptors.js +64 -0
  5. package/{source → dist-esm/src}/errors.js +0 -0
  6. package/dist-esm/src/fileDescriptor.browser.js +44 -0
  7. package/dist-esm/src/fileDescriptor.js +81 -0
  8. package/{index.js → dist-esm/src/index.js} +12 -10
  9. package/dist-esm/src/ingestClient.browser.js +43 -0
  10. package/dist-esm/src/ingestClient.js +45 -0
  11. package/dist-esm/src/ingestClientBase.js +47 -0
  12. package/{source → dist-esm/src}/ingestionBlobInfo.js +1 -5
  13. package/{source → dist-esm/src}/ingestionProperties.js +0 -0
  14. package/{source → dist-esm/src}/managedStreamingIngestClient.js +36 -38
  15. package/dist-esm/src/resourceManager.js +142 -0
  16. package/dist-esm/src/retry.js +37 -0
  17. package/{source → dist-esm/src}/status.js +0 -0
  18. package/dist-esm/src/statusQ.js +119 -0
  19. package/dist-esm/src/streamUtils.browser.js +22 -0
  20. package/{source → dist-esm/src}/streamUtils.js +24 -19
  21. package/dist-esm/src/streamingIngestClient.browser.js +42 -0
  22. package/dist-esm/src/streamingIngestClient.js +51 -0
  23. package/dist-esm/tsconfig.tsbuildinfo +1 -0
  24. package/package.json +35 -20
  25. package/{source → types/src}/abstractKustoClient.d.ts +4 -5
  26. package/{source → types/src}/columnMappings.d.ts +1 -0
  27. package/types/src/descriptors.d.ts +39 -0
  28. package/{source → types/src}/errors.d.ts +1 -0
  29. package/types/src/fileDescriptor.browser.d.ts +16 -0
  30. package/types/src/fileDescriptor.d.ts +29 -0
  31. package/{index.d.ts → types/src/index.d.ts} +13 -11
  32. package/types/src/ingestClient.browser.d.ts +19 -0
  33. package/types/src/ingestClient.d.ts +21 -0
  34. package/types/src/ingestClientBase.d.ts +14 -0
  35. package/{source → types/src}/ingestionBlobInfo.d.ts +2 -2
  36. package/{source → types/src}/ingestionProperties.d.ts +1 -0
  37. package/{source → types/src}/managedStreamingIngestClient.d.ts +12 -4
  38. package/{source → types/src}/resourceManager.d.ts +7 -5
  39. package/{source → types/src}/retry.d.ts +1 -0
  40. package/{source → types/src}/status.d.ts +1 -0
  41. package/{source → types/src}/statusQ.d.ts +1 -0
  42. package/types/src/streamUtils.browser.d.ts +7 -0
  43. package/types/src/streamUtils.d.ts +8 -0
  44. package/types/src/streamingIngestClient.browser.d.ts +21 -0
  45. package/types/src/streamingIngestClient.d.ts +23 -0
  46. package/example.js +0 -128
  47. package/source/descriptors.d.ts +0 -37
  48. package/source/descriptors.js +0 -125
  49. package/source/ingestClient.d.ts +0 -19
  50. package/source/ingestClient.js +0 -104
  51. package/source/resourceManager.js +0 -158
  52. package/source/retry.js +0 -48
  53. package/source/statusQ.js +0 -138
  54. package/source/streamUtils.d.ts +0 -6
  55. package/source/streamingIngestClient.d.ts +0 -15
  56. package/source/streamingIngestClient.js +0 -52
  57. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,23 @@
1
+ /// <reference types="node" />
2
+ import { IngestionPropertiesInput } from "./ingestionProperties";
3
+ import { StreamDescriptor } from "./descriptors";
4
+ import { FileDescriptor } from "./fileDescriptor";
5
+ import { AbstractKustoClient } from "./abstractKustoClient";
6
+ import { KustoConnectionStringBuilder } from "azure-kusto-data";
7
+ import { KustoResponseDataSet } from "azure-kusto-data/src/response";
8
+ import { Readable } from "stream";
9
+ declare class KustoStreamingIngestClient extends AbstractKustoClient {
10
+ private kustoClient;
11
+ constructor(kcsb: string | KustoConnectionStringBuilder, defaultProps?: IngestionPropertiesInput);
12
+ /**
13
+ * Use Readable for Node.js and ArrayBuffer in browser
14
+ */
15
+ ingestFromStream(stream: StreamDescriptor | Readable | ArrayBuffer, ingestionProperties?: IngestionPropertiesInput, clientRequestId?: string): Promise<any>;
16
+ /**
17
+ * Use string for Node.js and Blob in browser
18
+ */
19
+ ingestFromFile(file: FileDescriptor | string | Blob, ingestionProperties?: IngestionPropertiesInput): Promise<KustoResponseDataSet>;
20
+ close(): void;
21
+ }
22
+ export default KustoStreamingIngestClient;
23
+ //# sourceMappingURL=streamingIngestClient.d.ts.map
package/example.js DELETED
@@ -1,128 +0,0 @@
1
- // Copyright (c) Microsoft Corporation.
2
- // Licensed under the MIT License.
3
-
4
- const IngestClient = require("azure-kusto-ingest").IngestClient;
5
- const IngestStatusQueues = require("azure-kusto-ingest").IngestStatusQueues;
6
- const IngestionProps = require("azure-kusto-ingest").IngestionProperties;
7
- const KustoConnectionStringBuilder = require("azure-kusto-data").KustoConnectionStringBuilder;
8
- const { DataFormat, JsonColumnMapping, IngestionMappingKind, CompressionType, ReportLevel, ReportMethod } = require("azure-kusto-ingest");
9
- const { BlobDescriptor, StreamDescriptor } = require("azure-kusto-ingest").IngestionDescriptors;
10
- const StreamingIngestClient = require("azure-kusto-ingest").StreamingIngestClient;
11
- const fs = require("fs");
12
-
13
- const clusterName = null;
14
- const appId = null;
15
- const appKey = null;
16
- const authorityId = null;
17
-
18
- const props = new IngestionProps({
19
- database: "Database",
20
- table: "Table",
21
- format: DataFormat.JSON,
22
- ingestionMapping: [
23
- new JsonColumnMapping("TargetColumn1", "$.sourceProp1"),
24
- new JsonColumnMapping("TargetColumn2", "$.sourceProp2"),
25
- new JsonColumnMapping("TargetColumn3", "$.sourceProp3"),
26
- ],
27
- ingestionMappingType: IngestionMappingKind.JSON,
28
- reportLevel: ReportLevel.FailuresAndSuccesses,
29
- reportMethod: ReportMethod.Queue,
30
- });
31
-
32
- // After using the client, you should use `close()` to free up resources
33
- const ingestClient = new IngestClient(
34
- KustoConnectionStringBuilder.withAadApplicationKeyAuthentication(`https://ingest-${clusterName}.kusto.windows.net`, appId, appKey, authorityId),
35
- props
36
- );
37
-
38
- const statusQueues = new IngestStatusQueues(ingestClient);
39
-
40
- startIngestion();
41
-
42
- // Streaming ingest client
43
- const props2 = new IngestionProps({
44
- database: "Database",
45
- table: "Table",
46
- format: DataFormat.JSON,
47
- ingestionMappingReference: "Pre-defined mapping name",
48
- });
49
-
50
- // Init with engine endpoint
51
- const streamingIngestClient = new StreamingIngestClient(
52
- KustoConnectionStringBuilder.withAadApplicationKeyAuthentication(`https://${clusterName}.kusto.windows.net`, appId, appKey, authorityId),
53
- props2
54
- );
55
-
56
- startStreamingIngestion();
57
-
58
- async function startIngestion() {
59
- console.log("Ingest from file");
60
- try {
61
- await ingestClient.ingestFromFile("file.json");
62
- console.log("Ingestion done?");
63
-
64
- await waitForStatus();
65
- } catch (err) {
66
- console.log(err);
67
- }
68
-
69
- try {
70
- await ingestClient.ingestFromBlob(new BlobDescriptor("https://<account>.blob.core.windows.net/<container>/file.json.gz", 1024 * 50 /* 50MB file */));
71
- console.log("Ingestion done?");
72
-
73
- await waitForStatus();
74
- } catch (err) {
75
- console.log(err);
76
- }
77
- }
78
-
79
- async function waitForStatus(numberOFIngestions = 1) {
80
- while ((await statusQueues.failure.isEmpty()) && (await statusQueues.success.isEmpty())) {
81
- console.log("Waiting for status...");
82
- await sleep(1000);
83
- }
84
-
85
- const failures = await statusQueues.failure.pop(numberOFIngestions);
86
- for (let failure of failures) {
87
- console.log(`Failed: ${JSON.stringify(failure)}`);
88
- }
89
- const successes = await statusQueues.success.pop(numberOFIngestions);
90
- for (let success of successes) {
91
- console.log(`Succeeded: ${JSON.stringify(success)}`);
92
- }
93
- }
94
-
95
- function sleep(ms) {
96
- return new Promise((resolve) => {
97
- setTimeout(resolve, ms);
98
- });
99
- }
100
-
101
- async function startStreamingIngestion() {
102
- // Ingest from file with either file path or FileDescriptor
103
- try {
104
- await streamingIngestClient.ingestFromFile("file.json", props2);
105
- console.log("Ingestion done");
106
- } catch (err) {
107
- console.log(err);
108
- }
109
-
110
- // Ingest from stream with either ReadStream or StreamDescriptor
111
- let stream = fs.createReadStream("file.json");
112
- try {
113
- await streamingIngestClient.ingestFromStream(stream, props2);
114
- console.log("Ingestion done");
115
- } catch (err) {
116
- console.log(err);
117
- }
118
-
119
- // For gzip data set StreamDescriptor.compressionType to CompressionType.GZIP
120
- stream = fs.createReadStream("file.json.gz");
121
- const streamDescriptor = new StreamDescriptor(stream, "id", CompressionType.GZIP);
122
- try {
123
- await streamingIngestClient.ingestFromStream(streamDescriptor, props2);
124
- console.log("Ingestion done");
125
- } catch (err) {
126
- console.log(err);
127
- }
128
- }
@@ -1,37 +0,0 @@
1
- /// <reference types="node" />
2
- import { Readable } from "stream";
3
- export declare enum CompressionType {
4
- ZIP = ".zip",
5
- GZIP = ".gz",
6
- None = ""
7
- }
8
- export declare class FileDescriptor {
9
- readonly filePath: string;
10
- readonly name: string;
11
- readonly extension: string;
12
- size: number | null;
13
- sourceId: string;
14
- zipped: boolean;
15
- compressionType: CompressionType;
16
- cleanupTmp?: () => Promise<void>;
17
- constructor(filePath: string, sourceId?: string | null, size?: number | null, compressionType?: CompressionType);
18
- _gzip(): Promise<string>;
19
- prepare(): Promise<string>;
20
- private calculateSize;
21
- cleanup(): Promise<void>;
22
- }
23
- export declare class StreamDescriptor {
24
- readonly stream: Readable;
25
- name: string;
26
- size: number | null;
27
- compressionType: CompressionType;
28
- sourceId: string;
29
- constructor(stream: Readable, sourceId?: string | null, compressionType?: CompressionType);
30
- merge(other: StreamDescriptor): this;
31
- }
32
- export declare class BlobDescriptor {
33
- readonly path: string;
34
- size: number | null;
35
- sourceId: string;
36
- constructor(path: string, size?: number | null, sourceId?: string | null);
37
- }
@@ -1,125 +0,0 @@
1
- "use strict";
2
- // Copyright (c) Microsoft Corporation.
3
- // Licensed under the MIT License.
4
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6
- return new (P || (P = Promise))(function (resolve, reject) {
7
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
9
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10
- step((generator = generator.apply(thisArg, _arguments || [])).next());
11
- });
12
- };
13
- var __importDefault = (this && this.__importDefault) || function (mod) {
14
- return (mod && mod.__esModule) ? mod : { "default": mod };
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.BlobDescriptor = exports.StreamDescriptor = exports.FileDescriptor = exports.CompressionType = void 0;
18
- const uuid_1 = require("uuid");
19
- const uuid_validate_1 = __importDefault(require("uuid-validate"));
20
- const zlib_1 = __importDefault(require("zlib"));
21
- const path_1 = __importDefault(require("path"));
22
- const fs_1 = __importDefault(require("fs"));
23
- const tmp_promise_1 = require("tmp-promise");
24
- const util_1 = require("util");
25
- var CompressionType;
26
- (function (CompressionType) {
27
- CompressionType["ZIP"] = ".zip";
28
- CompressionType["GZIP"] = ".gz";
29
- CompressionType["None"] = "";
30
- })(CompressionType = exports.CompressionType || (exports.CompressionType = {}));
31
- const getSourceId = (sourceId) => {
32
- if (sourceId) {
33
- if (!(0, uuid_validate_1.default)(sourceId, 4)) {
34
- throw Error("sourceId is not a valid uuid/v4");
35
- }
36
- return sourceId;
37
- }
38
- return (0, uuid_1.v4)();
39
- };
40
- class FileDescriptor {
41
- constructor(filePath, sourceId = null, size = null, compressionType = CompressionType.None) {
42
- this.filePath = filePath;
43
- this.compressionType = compressionType;
44
- this.name = path_1.default.basename(this.filePath);
45
- this.extension = path_1.default.extname(this.filePath).toLowerCase();
46
- this.size = size;
47
- this.zipped = compressionType !== CompressionType.None || this.extension === ".gz" || this.extension === ".zip";
48
- this.sourceId = getSourceId(sourceId);
49
- }
50
- _gzip() {
51
- return __awaiter(this, void 0, void 0, function* () {
52
- const { path, cleanup } = yield (0, tmp_promise_1.file)({ postfix: ".gz", keep: false });
53
- this.cleanupTmp = cleanup;
54
- const zipper = zlib_1.default.createGzip();
55
- const input = fs_1.default.createReadStream(this.filePath, { autoClose: true });
56
- const output = fs_1.default.createWriteStream(path);
57
- yield new Promise((resolve, reject) => {
58
- input
59
- .pipe(zipper)
60
- .pipe(output)
61
- .on("error", (err) => {
62
- reject(err);
63
- });
64
- output.once("close", () => {
65
- resolve(null);
66
- });
67
- });
68
- return path;
69
- });
70
- }
71
- prepare() {
72
- return __awaiter(this, void 0, void 0, function* () {
73
- if (this.zipped) {
74
- const estimatedCompressionModifier = 11;
75
- yield this.calculateSize(estimatedCompressionModifier);
76
- return this.filePath;
77
- }
78
- const path = yield this._gzip();
79
- yield this.calculateSize();
80
- return path;
81
- });
82
- }
83
- calculateSize(modifier = 1) {
84
- return __awaiter(this, void 0, void 0, function* () {
85
- if (this.size == null || this.size <= 0) {
86
- const asyncStat = (0, util_1.promisify)(fs_1.default.stat);
87
- this.size = (yield asyncStat(this.filePath)).size * modifier;
88
- }
89
- });
90
- }
91
- cleanup() {
92
- return __awaiter(this, void 0, void 0, function* () {
93
- if (this.cleanupTmp) {
94
- yield this.cleanupTmp();
95
- }
96
- });
97
- }
98
- }
99
- exports.FileDescriptor = FileDescriptor;
100
- class StreamDescriptor {
101
- constructor(stream, sourceId = null, compressionType = CompressionType.None) {
102
- this.stream = stream;
103
- this.name = "stream";
104
- this.size = null;
105
- this.compressionType = compressionType;
106
- this.sourceId = getSourceId(sourceId);
107
- }
108
- merge(other) {
109
- this.name = other.name;
110
- this.size = other.size;
111
- this.compressionType = other.compressionType;
112
- this.sourceId = other.sourceId;
113
- return this;
114
- }
115
- }
116
- exports.StreamDescriptor = StreamDescriptor;
117
- class BlobDescriptor {
118
- constructor(path, size = null, sourceId = null) {
119
- this.path = path;
120
- this.size = size;
121
- this.sourceId = getSourceId(sourceId);
122
- }
123
- }
124
- exports.BlobDescriptor = BlobDescriptor;
125
- //# sourceMappingURL=descriptors.js.map
@@ -1,19 +0,0 @@
1
- /// <reference types="node" />
2
- import { KustoConnectionStringBuilder } from "azure-kusto-data";
3
- import { BlobDescriptor, CompressionType, FileDescriptor, StreamDescriptor } from "./descriptors";
4
- import ResourceManager from "./resourceManager";
5
- import { QueueSendMessageResponse } from "@azure/storage-queue";
6
- import { IngestionPropertiesInput } from "./ingestionProperties";
7
- import { AbstractKustoClient } from "./abstractKustoClient";
8
- import { Readable } from "stream";
9
- export declare class KustoIngestClient extends AbstractKustoClient {
10
- resourceManager: ResourceManager;
11
- constructor(kcsb: string | KustoConnectionStringBuilder, defaultProps?: IngestionPropertiesInput);
12
- _getBlobNameSuffix(format: string | null, compressionType: CompressionType): string;
13
- _getBlockBlobClient(blobName: string): Promise<import("@azure/storage-blob").BlockBlobClient>;
14
- ingestFromStream(stream: StreamDescriptor | Readable, ingestionProperties?: IngestionPropertiesInput): Promise<QueueSendMessageResponse>;
15
- ingestFromFile(file: string | FileDescriptor, ingestionProperties?: IngestionPropertiesInput): Promise<QueueSendMessageResponse>;
16
- ingestFromBlob(blob: string | BlobDescriptor, ingestionProperties?: IngestionPropertiesInput): Promise<QueueSendMessageResponse>;
17
- close(): void;
18
- }
19
- export default KustoIngestClient;
@@ -1,104 +0,0 @@
1
- "use strict";
2
- // Copyright (c) Microsoft Corporation.
3
- // Licensed under the MIT License.
4
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6
- return new (P || (P = Promise))(function (resolve, reject) {
7
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
9
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10
- step((generator = generator.apply(thisArg, _arguments || [])).next());
11
- });
12
- };
13
- var __importDefault = (this && this.__importDefault) || function (mod) {
14
- return (mod && mod.__esModule) ? mod : { "default": mod };
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.KustoIngestClient = void 0;
18
- const azure_kusto_data_1 = require("azure-kusto-data");
19
- const descriptors_1 = require("./descriptors");
20
- const resourceManager_1 = __importDefault(require("./resourceManager"));
21
- const ingestionBlobInfo_1 = __importDefault(require("./ingestionBlobInfo"));
22
- const storage_queue_1 = require("@azure/storage-queue");
23
- const storage_blob_1 = require("@azure/storage-blob");
24
- const abstractKustoClient_1 = require("./abstractKustoClient");
25
- const path_1 = __importDefault(require("path"));
26
- class KustoIngestClient extends abstractKustoClient_1.AbstractKustoClient {
27
- constructor(kcsb, defaultProps) {
28
- super(defaultProps);
29
- const kustoClient = new azure_kusto_data_1.Client(kcsb);
30
- this.resourceManager = new resourceManager_1.default(kustoClient);
31
- this.defaultDatabase = kustoClient.defaultDatabase;
32
- }
33
- _getBlobNameSuffix(format, compressionType) {
34
- const formatSuffix = format ? `.${format}` : "";
35
- return `${formatSuffix}${compressionType}`;
36
- }
37
- _getBlockBlobClient(blobName) {
38
- return __awaiter(this, void 0, void 0, function* () {
39
- const containers = yield this.resourceManager.getContainers();
40
- if (containers == null) {
41
- throw new Error("Failed to get containers");
42
- }
43
- const container = containers[Math.floor(Math.random() * containers.length)];
44
- const containerClient = new storage_blob_1.ContainerClient(container.uri);
45
- return containerClient.getBlockBlobClient(blobName);
46
- });
47
- }
48
- ingestFromStream(stream, ingestionProperties) {
49
- var _a;
50
- return __awaiter(this, void 0, void 0, function* () {
51
- this.ensureOpen();
52
- const props = this._getMergedProps(ingestionProperties);
53
- const descriptor = stream instanceof descriptors_1.StreamDescriptor ? stream : new descriptors_1.StreamDescriptor(stream);
54
- const blobName = `${props.database}__${props.table}__${descriptor.sourceId}` + `${this._getBlobNameSuffix((_a = props.format) !== null && _a !== void 0 ? _a : "", descriptor.compressionType)}`;
55
- const blockBlobClient = yield this._getBlockBlobClient(blobName);
56
- yield blockBlobClient.uploadStream(descriptor.stream);
57
- return this.ingestFromBlob(new descriptors_1.BlobDescriptor(blockBlobClient.url), props); // descriptor.size?
58
- });
59
- }
60
- ingestFromFile(file, ingestionProperties) {
61
- return __awaiter(this, void 0, void 0, function* () {
62
- this.ensureOpen();
63
- const props = this._getMergedProps(ingestionProperties);
64
- const descriptor = file instanceof descriptors_1.FileDescriptor ? file : new descriptors_1.FileDescriptor(file);
65
- try {
66
- const fileToUpload = yield descriptor.prepare();
67
- const blobName = `${props.database}__${props.table}__${descriptor.sourceId}__${descriptor.name}__.${path_1.default.extname(fileToUpload)}`;
68
- const blockBlobClient = yield this._getBlockBlobClient(blobName);
69
- yield blockBlobClient.uploadFile(fileToUpload);
70
- return this.ingestFromBlob(new descriptors_1.BlobDescriptor(blockBlobClient.url, descriptor.size, descriptor.sourceId), props);
71
- }
72
- finally {
73
- yield descriptor.cleanup();
74
- }
75
- });
76
- }
77
- ingestFromBlob(blob, ingestionProperties) {
78
- return __awaiter(this, void 0, void 0, function* () {
79
- this.ensureOpen();
80
- const props = this._getMergedProps(ingestionProperties);
81
- const descriptor = blob instanceof descriptors_1.BlobDescriptor ? blob : new descriptors_1.BlobDescriptor(blob);
82
- const queues = yield this.resourceManager.getIngestionQueues();
83
- if (queues == null) {
84
- throw new Error("Failed to get queues");
85
- }
86
- const authorizationContext = yield this.resourceManager.getAuthorizationContext();
87
- const queueDetails = queues[Math.floor(Math.random() * queues.length)];
88
- const queueClient = new storage_queue_1.QueueClient(queueDetails.uri);
89
- const ingestionBlobInfo = new ingestionBlobInfo_1.default(descriptor, props, authorizationContext);
90
- const ingestionBlobInfoJson = JSON.stringify(ingestionBlobInfo);
91
- const encoded = Buffer.from(ingestionBlobInfoJson).toString("base64");
92
- return queueClient.sendMessage(encoded);
93
- });
94
- }
95
- close() {
96
- if (!this._isClosed) {
97
- this.resourceManager.close();
98
- }
99
- super.close();
100
- }
101
- }
102
- exports.KustoIngestClient = KustoIngestClient;
103
- exports.default = KustoIngestClient;
104
- //# sourceMappingURL=ingestClient.js.map
@@ -1,158 +0,0 @@
1
- "use strict";
2
- // Copyright (c) Microsoft Corporation.
3
- // Licensed under the MIT License.
4
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6
- return new (P || (P = Promise))(function (resolve, reject) {
7
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
9
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10
- step((generator = generator.apply(thisArg, _arguments || [])).next());
11
- });
12
- };
13
- var __importDefault = (this && this.__importDefault) || function (mod) {
14
- return (mod && mod.__esModule) ? mod : { "default": mod };
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.ResourceManager = exports.IngestClientResources = exports.ResourceURI = void 0;
18
- const azure_kusto_data_1 = require("azure-kusto-data");
19
- const retry_1 = require("./retry");
20
- const moment_1 = __importDefault(require("moment"));
21
- const ATTEMPT_COUNT = 4;
22
- class ResourceURI {
23
- constructor(uri) {
24
- this.uri = uri;
25
- }
26
- }
27
- exports.ResourceURI = ResourceURI;
28
- class IngestClientResources {
29
- constructor(securedReadyForAggregationQueues = null, failedIngestionsQueues = null, successfulIngestionsQueues = null, containers = null) {
30
- this.securedReadyForAggregationQueues = securedReadyForAggregationQueues;
31
- this.failedIngestionsQueues = failedIngestionsQueues;
32
- this.successfulIngestionsQueues = successfulIngestionsQueues;
33
- this.containers = containers;
34
- }
35
- valid() {
36
- const resources = [this.securedReadyForAggregationQueues, this.failedIngestionsQueues, this.failedIngestionsQueues, this.containers];
37
- return resources.reduce((prev, current) => !!(prev && current), true);
38
- }
39
- }
40
- exports.IngestClientResources = IngestClientResources;
41
- class ResourceManager {
42
- constructor(kustoClient) {
43
- this.kustoClient = kustoClient;
44
- this.baseSleepTimeSecs = 1;
45
- this.baseJitterSecs = 1;
46
- this.refreshPeriod = moment_1.default.duration(1, "h");
47
- this.ingestClientResources = null;
48
- this.ingestClientResourcesNextUpdate = (0, moment_1.default)();
49
- this.authorizationContext = null;
50
- this.authorizationContextNextUpdate = (0, moment_1.default)();
51
- }
52
- refreshIngestClientResources() {
53
- return __awaiter(this, void 0, void 0, function* () {
54
- const now = (0, moment_1.default)();
55
- if (!this.ingestClientResources || this.ingestClientResourcesNextUpdate <= now || !this.ingestClientResources.valid()) {
56
- this.ingestClientResources = yield this.getIngestClientResourcesFromService();
57
- this.ingestClientResourcesNextUpdate = (0, moment_1.default)().add(this.refreshPeriod);
58
- }
59
- return this.ingestClientResources;
60
- });
61
- }
62
- getIngestClientResourcesFromService() {
63
- return __awaiter(this, void 0, void 0, function* () {
64
- const retry = new retry_1.ExponentialRetry(ATTEMPT_COUNT, this.baseSleepTimeSecs, this.baseJitterSecs);
65
- while (retry.shouldTry()) {
66
- try {
67
- const response = yield this.kustoClient.execute("NetDefaultDB", ".get ingestion resources");
68
- const table = response.primaryResults[0];
69
- return new IngestClientResources(this.getResourceByName(table, "SecuredReadyForAggregationQueue"), this.getResourceByName(table, "FailedIngestionsQueue"), this.getResourceByName(table, "SuccessfulIngestionsQueue"), this.getResourceByName(table, "TempStorage"));
70
- }
71
- catch (error) {
72
- if (!(error instanceof azure_kusto_data_1.KustoDataErrors.ThrottlingError)) {
73
- throw error;
74
- }
75
- yield retry.backoff();
76
- }
77
- }
78
- throw new Error(`Failed to get ingestion resources from server - the request was throttled ${ATTEMPT_COUNT} times.`);
79
- });
80
- }
81
- getResourceByName(table, resourceName) {
82
- const result = [];
83
- for (const row of table.rows()) {
84
- const typedRow = row;
85
- if (typedRow.ResourceTypeName === resourceName) {
86
- result.push(new ResourceURI(typedRow.StorageRoot));
87
- }
88
- }
89
- return result;
90
- }
91
- refreshAuthorizationContext() {
92
- var _a;
93
- return __awaiter(this, void 0, void 0, function* () {
94
- const now = moment_1.default.utc();
95
- if (!((_a = this.authorizationContext) === null || _a === void 0 ? void 0 : _a.trim()) || this.authorizationContextNextUpdate <= now) {
96
- this.authorizationContext = yield this.getAuthorizationContextFromService();
97
- this.authorizationContextNextUpdate = (0, moment_1.default)().add(this.refreshPeriod);
98
- if (this.authorizationContext == null) {
99
- throw new Error("Authorization context can't be null");
100
- }
101
- }
102
- return this.authorizationContext;
103
- });
104
- }
105
- getAuthorizationContextFromService() {
106
- return __awaiter(this, void 0, void 0, function* () {
107
- const retry = new retry_1.ExponentialRetry(ATTEMPT_COUNT, this.baseSleepTimeSecs, this.baseJitterSecs);
108
- while (retry.shouldTry()) {
109
- try {
110
- const response = yield this.kustoClient.execute("NetDefaultDB", ".get kusto identity token");
111
- const next = response.primaryResults[0].rows().next();
112
- if (next.done) {
113
- throw new Error("Failed to get authorization context - got empty results");
114
- }
115
- return next.value.toJSON().AuthorizationContext;
116
- }
117
- catch (error) {
118
- if (!(error instanceof azure_kusto_data_1.KustoDataErrors.ThrottlingError)) {
119
- throw error;
120
- }
121
- yield retry.backoff();
122
- }
123
- }
124
- throw new Error(`Failed to get identity token from server - the request was throttled ${ATTEMPT_COUNT} times.`);
125
- });
126
- }
127
- getIngestionQueues() {
128
- return __awaiter(this, void 0, void 0, function* () {
129
- return (yield this.refreshIngestClientResources()).securedReadyForAggregationQueues;
130
- });
131
- }
132
- getFailedIngestionsQueues() {
133
- return __awaiter(this, void 0, void 0, function* () {
134
- return (yield this.refreshIngestClientResources()).failedIngestionsQueues;
135
- });
136
- }
137
- getSuccessfulIngestionsQueues() {
138
- return __awaiter(this, void 0, void 0, function* () {
139
- return (yield this.refreshIngestClientResources()).successfulIngestionsQueues;
140
- });
141
- }
142
- getContainers() {
143
- return __awaiter(this, void 0, void 0, function* () {
144
- return (yield this.refreshIngestClientResources()).containers;
145
- });
146
- }
147
- getAuthorizationContext() {
148
- return __awaiter(this, void 0, void 0, function* () {
149
- return this.refreshAuthorizationContext();
150
- });
151
- }
152
- close() {
153
- this.kustoClient.close();
154
- }
155
- }
156
- exports.ResourceManager = ResourceManager;
157
- exports.default = ResourceManager;
158
- //# sourceMappingURL=resourceManager.js.map
package/source/retry.js DELETED
@@ -1,48 +0,0 @@
1
- "use strict";
2
- // Copyright (c) Microsoft Corporation.
3
- // Licensed under the MIT License.
4
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6
- return new (P || (P = Promise))(function (resolve, reject) {
7
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
9
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10
- step((generator = generator.apply(thisArg, _arguments || [])).next());
11
- });
12
- };
13
- Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.ExponentialRetry = exports.sleep = void 0;
15
- const sleep = (ms) => {
16
- return new Promise((resolve) => {
17
- setTimeout(resolve, ms);
18
- });
19
- };
20
- exports.sleep = sleep;
21
- class ExponentialRetry {
22
- constructor(attemptCount, sleepBaseSecs, maxJitterSecs) {
23
- this.attemptCount = attemptCount;
24
- this.sleepBaseSecs = sleepBaseSecs;
25
- this.maxJitterSecs = maxJitterSecs;
26
- this.currentAttempt = 0;
27
- }
28
- backoff() {
29
- return __awaiter(this, void 0, void 0, function* () {
30
- if (!this.shouldTry()) {
31
- throw new Error("Max retries exceeded");
32
- }
33
- this.currentAttempt++;
34
- if (!this.shouldTry()) {
35
- // This was the last retry - no need to sleep
36
- return;
37
- }
38
- const base = this.sleepBaseSecs * Math.pow(2, this.currentAttempt - 1);
39
- const jitter = Math.floor(this.maxJitterSecs * Math.random());
40
- yield (0, exports.sleep)(1000 * (base + jitter));
41
- });
42
- }
43
- shouldTry() {
44
- return this.currentAttempt < this.attemptCount;
45
- }
46
- }
47
- exports.ExponentialRetry = ExponentialRetry;
48
- //# sourceMappingURL=retry.js.map