@volant-autonomy/via-sdk 1.3748.1 → 1.3760.1

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/dist/index.esm.js CHANGED
@@ -13,6 +13,12 @@ class UnauthenticatedError extends Error {
13
13
  }
14
14
  }
15
15
 
16
+ class StreamFailedError extends Error {
17
+ }
18
+ class TaskTimeoutError extends Error {
19
+ }
20
+ const PathingTaskTimeout = 30000;
21
+ const ValidStreamTimeout = 5000;
16
22
  class Composite {
17
23
  constructor(direct) {
18
24
  this.direct = direct;
@@ -53,36 +59,107 @@ class Composite {
53
59
  return this.direct.modifyDraftFlightplan(id, data.attributes);
54
60
  }
55
61
  /// pathing tasks
56
- /** Handles creating and polling a pathing task for you */
57
- async doPathingTask(args) {
58
- var _a, _b;
59
- const { error, data } = await this.direct.createPathingTask(args);
60
- if (error) {
61
- return { error };
62
+ /**
63
+ * Handles fetching a pathing task once it has reached a final state. This will be completed through one of two
64
+ * methods:
65
+ *
66
+ * - Event stream (default) - Opens an event stream and optionally calls onMessage when the state changes. The
67
+ * callback will not be called once the task is complete as the task being complete can be inferred from the stream
68
+ * being closed.
69
+ *
70
+ * - Polling (fallback) - Occurs automatically if the connection to the event stream is unsuccessful or the stream
71
+ * fails. Polls every 0.5s whilst queuing and every 0.2s whilst in progress. Note if onMessage is defined it is
72
+ * called on every poll.
73
+ * @param taskId - A UUID value that identifies a pathing task
74
+ * @param onMessage - Callback that is called upon receiving details on the state of the pathing task
75
+ * @returns - The result of the pathing task
76
+ */
77
+ async getPathingTaskResult(taskId, onMessage) {
78
+ try {
79
+ await this.pathingTaskStreamResult(taskId, onMessage);
80
+ }
81
+ catch (error) {
82
+ if (error instanceof StreamFailedError) {
83
+ await this.pathingTaskPollResult(taskId, onMessage);
84
+ }
62
85
  }
63
- const id = data.id;
64
- while (true) {
65
- const { data, error } = await this.direct.getPathingTask(id);
66
- if (error) {
67
- return { error };
86
+ return this.direct.getPathingTask(taskId);
87
+ }
88
+ /** Handles creating and waiting for the result of a pathing task. */
89
+ async doPathingTask(args) {
90
+ const createdTask = await this.direct.createPathingTask(args);
91
+ if (createdTask.error) {
92
+ return createdTask.error;
93
+ }
94
+ const id = createdTask.data.id;
95
+ return await this.getPathingTaskResult(id);
96
+ }
97
+ async pathingTaskStreamResult(taskId, onMessage) {
98
+ let streamConnectionTimeout;
99
+ let streamNotSuccessfulTimeout;
100
+ const promise = new Promise((resolve, reject) => {
101
+ const stream = this.direct.getPathingTaskStateStream(taskId);
102
+ streamConnectionTimeout = setTimeout(() => {
103
+ if (stream.readyState !== EventSource.OPEN) {
104
+ stream.close();
105
+ reject(new StreamFailedError('Timeout connecting'));
106
+ }
107
+ }, ValidStreamTimeout);
108
+ streamNotSuccessfulTimeout = setTimeout(() => {
109
+ stream.close();
110
+ reject(new TaskTimeoutError('Timeout whilst waiting for successful result'));
111
+ }, PathingTaskTimeout);
112
+ stream.onmessage = async (event) => {
113
+ // TODO(Jack): Use a discriminated union
114
+ const data = JSON.parse(event.data);
115
+ if (data.error === true) {
116
+ stream.close();
117
+ reject(new Error(`Task stream returned error: ${data.payload}`));
118
+ return;
119
+ }
120
+ onMessage === null || onMessage === void 0 ? void 0 : onMessage(data.payload);
121
+ if (data.payload.terminated === true) {
122
+ stream.close();
123
+ resolve(data.payload);
124
+ }
125
+ };
126
+ stream.onerror = (error) => {
127
+ stream.close();
128
+ reject(new StreamFailedError(`Stream failed: ${error}`));
129
+ };
130
+ });
131
+ return promise.finally(() => {
132
+ clearTimeout(streamConnectionTimeout);
133
+ clearTimeout(streamNotSuccessfulTimeout);
134
+ });
135
+ }
136
+ async pathingTaskPollResult(taskId, onMessage) {
137
+ let runPathing = true;
138
+ while (runPathing) {
139
+ setTimeout(() => {
140
+ runPathing = false;
141
+ }, PathingTaskTimeout);
142
+ const pathingTaskResult = await this.direct.getPathingTask(taskId);
143
+ if (pathingTaskResult.error) {
144
+ return pathingTaskResult.error;
145
+ }
146
+ if (pathingTaskResult.data.meta.state === 'successful' ||
147
+ pathingTaskResult.data.meta.state === 'failed') {
148
+ return;
68
149
  }
69
- switch (data.meta.state) {
150
+ const pathingTaskPayload = {
151
+ state: pathingTaskResult.data.meta.state,
152
+ terminated: false
153
+ };
154
+ // TODO: Make this only on change from previous
155
+ onMessage === null || onMessage === void 0 ? void 0 : onMessage(pathingTaskPayload);
156
+ switch (pathingTaskResult.data.meta.state) {
70
157
  case 'queued':
71
158
  await sleep(500);
72
- continue;
159
+ break;
73
160
  case 'in-progress':
74
- await sleep(50);
75
- continue;
76
- case 'successful':
77
- if ((_a = data.attributes) === null || _a === void 0 ? void 0 : _a.waypoints) {
78
- return { data: (_b = data.attributes) === null || _b === void 0 ? void 0 : _b.waypoints };
79
- }
80
- else {
81
- throw new Error(`endpoint did not return waypoints ${data}`); // TODO:
82
- }
83
- case 'failed':
84
- // TODO: this is bad, do this better.
85
- return { error: data.meta.error_code };
161
+ await sleep(200);
162
+ break;
86
163
  }
87
164
  }
88
165
  }
@@ -219,28 +296,9 @@ class Direct {
219
296
  }
220
297
  return resp;
221
298
  }
222
- getPathingTaskStateStream(id, onMessage, onFail) {
223
- return new Promise((resolve, reject) => {
224
- const eventSource = new EventSource(`/api/v1.0/pathing_tasks/${id}/state`);
225
- eventSource.onmessage = (event) => {
226
- const data = JSON.parse(event.data);
227
- if (data.error === true) {
228
- onFail === null || onFail === void 0 ? void 0 : onFail();
229
- eventSource.close();
230
- reject(new Error(`Task stream returned error: ${data.payload}`));
231
- return;
232
- }
233
- if (data.payload.terminated) {
234
- eventSource.close();
235
- resolve(data.payload);
236
- }
237
- onMessage === null || onMessage === void 0 ? void 0 : onMessage(data.payload);
238
- };
239
- eventSource.onerror = (err) => {
240
- eventSource.close();
241
- onFail === null || onFail === void 0 ? void 0 : onFail();
242
- reject(err);
243
- };
299
+ getPathingTaskStateStream(id) {
300
+ return this.fetcher.STREAM(`/pathing_tasks/{pathing_task_id}/state`, {
301
+ path: { pathing_task_id: id }
244
302
  });
245
303
  }
246
304
  /// charts
@@ -725,7 +783,7 @@ function defaultPathSerializer(pathname, pathParams) {
725
783
  return nextURL;
726
784
  }
727
785
 
728
- var version = "1.3748.1";
786
+ var version = "1.3760.1";
729
787
 
730
788
  const querySerializer = createQuerySerializer();
731
789
  class Fetcher {
@@ -894,6 +952,14 @@ class Fetcher {
894
952
  async HEAD(path, data, opts) {
895
953
  return this.fetcher('post', path, data, opts);
896
954
  }
955
+ STREAM(path, data) {
956
+ const downcastedData = data;
957
+ const url = this.createFinalURL(path, {
958
+ query: downcastedData === null || downcastedData === void 0 ? void 0 : downcastedData.query,
959
+ path: downcastedData === null || downcastedData === void 0 ? void 0 : downcastedData.path
960
+ });
961
+ return new EventSource(url);
962
+ }
897
963
  }
898
964
  // indirection is required to get ts to accept the type magic
899
965
  //* * `paths` MUST be passed in as a generic type arg or type inference falls apart */