@blaxel/core 0.2.5 → 0.2.6-dev.74

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.
@@ -9,6 +9,8 @@ export declare class ClientCredentials extends Credentials {
9
9
  get workspace(): string;
10
10
  needRefresh(): boolean;
11
11
  authenticate(): Promise<void>;
12
+ private sleep;
13
+ processWithRetry(retry?: number): Promise<void>;
12
14
  process(): Promise<void>;
13
15
  get authorization(): string;
14
16
  get token(): string;
@@ -42,9 +42,24 @@ class ClientCredentials extends credentials_js_1.Credentials {
42
42
  if (!this.needRefresh()) {
43
43
  return this.currentPromise || Promise.resolve();
44
44
  }
45
- this.currentPromise = this.process();
45
+ this.currentPromise = this.processWithRetry();
46
46
  return this.currentPromise;
47
47
  }
48
+ sleep(ms) {
49
+ return new Promise((resolve) => setTimeout(resolve, ms));
50
+ }
51
+ async processWithRetry(retry = 3) {
52
+ try {
53
+ return await this.process();
54
+ }
55
+ catch (error) {
56
+ if (retry > 0) {
57
+ await this.sleep(1000);
58
+ return this.processWithRetry(retry - 1);
59
+ }
60
+ throw error;
61
+ }
62
+ }
48
63
  async process() {
49
64
  const response = await (0, authentication_js_1.oauthToken)({
50
65
  headers: {
@@ -1 +1,3 @@
1
1
  export * from "./jobs.js";
2
+ export * from "./start.js";
3
+ export * from "./types.js";
@@ -15,3 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./jobs.js"), exports);
18
+ __exportStar(require("./start.js"), exports);
19
+ __exportStar(require("./types.js"), exports);
@@ -1,11 +1,13 @@
1
1
  declare class BlJob {
2
- getArguments(): Promise<{
3
- [key: number]: any;
4
- }>;
5
- private parseCommandLineArgs;
6
- get indexKey(): string;
7
- get index(): number;
8
- start(func: (args: any) => Promise<void>): Promise<void>;
2
+ jobName: string;
3
+ constructor(jobName: string);
4
+ get fallbackUrl(): import("url").URL | null;
5
+ get externalUrl(): import("url").URL;
6
+ get internalUrl(): import("url").URL;
7
+ get forcedUrl(): import("url").URL | null;
8
+ get url(): import("url").URL;
9
+ call(url: URL, tasks: Record<string, unknown>[]): Promise<Response>;
10
+ run(tasks: Record<string, unknown>[]): Promise<string>;
9
11
  }
10
- export declare const blJob: BlJob;
12
+ export declare const blJob: (jobName: string) => BlJob;
11
13
  export {};
package/dist/jobs/jobs.js CHANGED
@@ -2,54 +2,94 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.blJob = void 0;
4
4
  const env_js_1 = require("../common/env.js");
5
+ const internal_js_1 = require("../common/internal.js");
6
+ const logger_js_1 = require("../common/logger.js");
7
+ const settings_js_1 = require("../common/settings.js");
8
+ const telemetry_js_1 = require("../telemetry/telemetry.js");
5
9
  class BlJob {
6
- async getArguments() {
7
- if (!env_js_1.env.BL_EXECUTION_DATA_URL) {
8
- const args = this.parseCommandLineArgs();
9
- return args;
10
+ jobName;
11
+ constructor(jobName) {
12
+ this.jobName = jobName;
13
+ }
14
+ get fallbackUrl() {
15
+ if (this.externalUrl != this.url) {
16
+ return this.externalUrl;
10
17
  }
11
- const response = await fetch(env_js_1.env.BL_EXECUTION_DATA_URL);
12
- const data = await response.json();
13
- return data.tasks[this.index] ?? {};
14
- }
15
- parseCommandLineArgs() {
16
- const args = process.argv.slice(2);
17
- const result = {};
18
- for (let i = 0; i < args.length; i++) {
19
- const arg = args[i];
20
- if (arg.startsWith('--')) {
21
- const key = arg.slice(2);
22
- const value = args[i + 1];
23
- if (value && !value.startsWith('--')) {
24
- result[key] = value;
25
- i++;
26
- }
27
- else {
28
- result[key] = 'true';
29
- }
30
- }
18
+ return null;
19
+ }
20
+ get externalUrl() {
21
+ return new URL(`${settings_js_1.settings.runUrl}/${settings_js_1.settings.workspace}/jobs/${this.jobName}`);
22
+ }
23
+ get internalUrl() {
24
+ const hash = (0, internal_js_1.getGlobalUniqueHash)(settings_js_1.settings.workspace, "job", this.jobName);
25
+ return new URL(`${settings_js_1.settings.runInternalProtocol}://bl-${settings_js_1.settings.env}-${hash}.${settings_js_1.settings.runInternalHostname}`);
26
+ }
27
+ get forcedUrl() {
28
+ const envVar = this.jobName.replace(/-/g, "_").toUpperCase();
29
+ if (env_js_1.env[`BL_JOB_${envVar}_URL`]) {
30
+ return new URL(env_js_1.env[`BL_JOB_${envVar}_URL`]);
31
31
  }
32
- return result;
32
+ return null;
33
33
  }
34
- get indexKey() {
35
- return env_js_1.env.BL_TASK_KEY ?? "TASK_INDEX";
34
+ get url() {
35
+ if (this.forcedUrl)
36
+ return this.forcedUrl;
37
+ if (settings_js_1.settings.runInternalHostname)
38
+ return this.internalUrl;
39
+ return this.externalUrl;
36
40
  }
37
- get index() {
38
- return env_js_1.env[this.indexKey] ? Number(env_js_1.env[this.indexKey]) ?? 0 : 0;
41
+ async call(url, tasks) {
42
+ let body = {
43
+ tasks: tasks
44
+ };
45
+ const response = await fetch(url + "/executions", {
46
+ method: "POST",
47
+ headers: {
48
+ ...settings_js_1.settings.headers,
49
+ "Content-Type": "application/json",
50
+ },
51
+ body: JSON.stringify(body),
52
+ });
53
+ return response;
39
54
  }
40
- /*
41
- Run a job defined in a function, it's run in the current process
42
- */
43
- async start(func) {
55
+ async run(tasks) {
56
+ logger_js_1.logger.debug(`Job Calling: ${this.jobName}`);
57
+ const span = (0, telemetry_js_1.startSpan)(this.jobName, {
58
+ attributes: {
59
+ "job.name": this.jobName,
60
+ "span.type": "job.run",
61
+ },
62
+ isRoot: false,
63
+ });
44
64
  try {
45
- const parsedArgs = await this.getArguments();
46
- await func(parsedArgs);
47
- process.exit(0);
65
+ const response = await this.call(this.url, tasks);
66
+ return await response.text();
67
+ }
68
+ catch (err) {
69
+ if (err instanceof Error) {
70
+ if (!this.fallbackUrl) {
71
+ span.setAttribute("job.run.error", err.stack);
72
+ throw err;
73
+ }
74
+ try {
75
+ const response = await this.call(this.fallbackUrl, tasks);
76
+ return await response.text();
77
+ }
78
+ catch (err) {
79
+ if (err instanceof Error) {
80
+ span.setAttribute("job.run.error", err.stack);
81
+ }
82
+ throw err;
83
+ }
84
+ }
85
+ throw err;
48
86
  }
49
- catch (error) {
50
- console.error('Job execution failed:', error);
51
- process.exit(1);
87
+ finally {
88
+ span.end();
52
89
  }
53
90
  }
54
91
  }
55
- exports.blJob = new BlJob();
92
+ const blJob = (jobName) => {
93
+ return new BlJob(jobName);
94
+ };
95
+ exports.blJob = blJob;
@@ -0,0 +1 @@
1
+ export declare const blStartJob: (func: (args: any) => Promise<void>) => void;
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.blStartJob = void 0;
4
+ const autoload_js_1 = require("../common/autoload.js");
5
+ const env_js_1 = require("../common/env.js");
6
+ const telemetry_js_1 = require("../telemetry/telemetry.js");
7
+ class BlJobWrapper {
8
+ async getArguments() {
9
+ if (!env_js_1.env.BL_EXECUTION_DATA_URL) {
10
+ const args = this.parseCommandLineArgs();
11
+ return args;
12
+ }
13
+ const response = await fetch(env_js_1.env.BL_EXECUTION_DATA_URL);
14
+ const data = await response.json();
15
+ return data.tasks[this.index] ?? {};
16
+ }
17
+ parseCommandLineArgs() {
18
+ const args = process.argv.slice(2);
19
+ const result = {};
20
+ for (let i = 0; i < args.length; i++) {
21
+ const arg = args[i];
22
+ if (arg.startsWith('--')) {
23
+ const key = arg.slice(2);
24
+ const value = args[i + 1];
25
+ if (value && !value.startsWith('--')) {
26
+ result[key] = value;
27
+ i++;
28
+ }
29
+ else {
30
+ result[key] = 'true';
31
+ }
32
+ }
33
+ }
34
+ return result;
35
+ }
36
+ get indexKey() {
37
+ return env_js_1.env.BL_TASK_KEY ?? "TASK_INDEX";
38
+ }
39
+ get index() {
40
+ return env_js_1.env[this.indexKey] ? Number(env_js_1.env[this.indexKey]) ?? 0 : 0;
41
+ }
42
+ /*
43
+ Run a job defined in a function, it's run in the current process
44
+ */
45
+ async start(func) {
46
+ await (0, autoload_js_1.authenticate)();
47
+ let span = (0, telemetry_js_1.startSpan)(`blStartJob-${func.name}`, {
48
+ attributes: {
49
+ 'job.name': func.name,
50
+ 'job.index': this.index,
51
+ 'job.args': JSON.stringify(this.getArguments()),
52
+ },
53
+ isRoot: true,
54
+ });
55
+ try {
56
+ const parsedArgs = await this.getArguments();
57
+ await func(parsedArgs);
58
+ span.setStatus('ok');
59
+ span.end();
60
+ }
61
+ catch (error) {
62
+ span.recordException(error);
63
+ span.setStatus('error', 'Job execution failed');
64
+ span.end();
65
+ throw error;
66
+ }
67
+ }
68
+ }
69
+ const blStartJob = (func) => {
70
+ const job = new BlJobWrapper();
71
+ job.start(func).then(async () => {
72
+ try {
73
+ await (0, telemetry_js_1.flush)();
74
+ }
75
+ catch (error) {
76
+ console.error('Error flushing telemetry:', error);
77
+ }
78
+ }).catch((error) => {
79
+ console.error('Job execution failed:', error);
80
+ process.exit(1);
81
+ });
82
+ };
83
+ exports.blStartJob = blStartJob;
@@ -0,0 +1,3 @@
1
+ export type ExecutionArgs = {
2
+ [key: number]: any;
3
+ }[];
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -32,6 +32,8 @@ export interface BlaxelSpan {
32
32
  export interface BlaxelTelemetryProvider {
33
33
  /** Create a new span */
34
34
  startSpan(name: string, options?: BlaxelSpanOptions): BlaxelSpan;
35
+ /** Flush the telemetry provider */
36
+ flush(): Promise<void>;
35
37
  }
36
38
  /**
37
39
  * Registry for managing the global telemetry provider
@@ -55,5 +57,6 @@ export declare const telemetryRegistry: TelemetryRegistry;
55
57
  * Create a span with the registered provider
56
58
  */
57
59
  export declare function startSpan(name: string, options?: BlaxelSpanOptions): BlaxelSpan;
58
- export declare function withSpan<T>(name: string, fn: () => T, options?: BlaxelSpanOptions): T;
60
+ export declare function withSpan<T>(name: string, fn: () => Promise<T>, options?: BlaxelSpanOptions): Promise<T>;
61
+ export declare function flush(): Promise<void>;
59
62
  export {};
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.telemetryRegistry = void 0;
5
5
  exports.startSpan = startSpan;
6
6
  exports.withSpan = withSpan;
7
+ exports.flush = flush;
7
8
  /**
8
9
  * No-operation implementation of Span
9
10
  */
@@ -22,6 +23,9 @@ class NoopTelemetryProvider {
22
23
  startSpan() {
23
24
  return new NoopSpan();
24
25
  }
26
+ flush() {
27
+ return Promise.resolve();
28
+ }
25
29
  }
26
30
  /**
27
31
  * Registry for managing the global telemetry provider
@@ -58,10 +62,10 @@ exports.telemetryRegistry = TelemetryRegistry.getInstance();
58
62
  function startSpan(name, options) {
59
63
  return exports.telemetryRegistry.getProvider().startSpan(name, options);
60
64
  }
61
- function withSpan(name, fn, options) {
65
+ async function withSpan(name, fn, options) {
62
66
  const span = startSpan(name, options);
63
67
  try {
64
- const result = fn();
68
+ const result = await fn();
65
69
  span.end();
66
70
  return result;
67
71
  }
@@ -71,3 +75,6 @@ function withSpan(name, fn, options) {
71
75
  throw error;
72
76
  }
73
77
  }
78
+ async function flush() {
79
+ await exports.telemetryRegistry.getProvider().flush();
80
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blaxel/core",
3
- "version": "0.2.5",
3
+ "version": "0.2.6-dev.74",
4
4
  "description": "Blaxel Core SDK for TypeScript",
5
5
  "license": "MIT",
6
6
  "author": "Blaxel, INC (https://blaxel.ai)",