@pipe0/client 1.0.1 → 1.0.2
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/CHANGELOG.md +6 -0
- package/README.md +26 -9
- package/dist/capacity-tracker.d.mts +64 -0
- package/dist/capacity-tracker.d.mts.map +1 -0
- package/dist/capacity-tracker.mjs +87 -0
- package/dist/capacity-tracker.mjs.map +1 -0
- package/dist/generated/openapi.types.d.mts +277 -33
- package/dist/generated/openapi.types.d.mts.map +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +3 -2
- package/dist/pipe0.d.mts +381 -12
- package/dist/pipe0.d.mts.map +1 -1
- package/dist/pipe0.mjs +311 -90
- package/dist/pipe0.mjs.map +1 -1
- package/package.json +2 -1
package/dist/pipe0.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CapacityTracker } from "./capacity-tracker.mjs";
|
|
1
2
|
import createFetchClient from "openapi-fetch";
|
|
2
3
|
|
|
3
4
|
//#region src/pipe0.ts
|
|
@@ -17,6 +18,17 @@ var Pipe0AbortError = class extends Error {
|
|
|
17
18
|
this.runId = runId;
|
|
18
19
|
}
|
|
19
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* The server reports the run as `canceled` (via `pipes.cancel` /
|
|
23
|
+
* `searches.cancel` or another client). Subclasses {@link Pipe0AbortError} so
|
|
24
|
+
* existing `instanceof Pipe0AbortError` handling keeps working.
|
|
25
|
+
*/
|
|
26
|
+
var Pipe0CanceledError = class extends Pipe0AbortError {
|
|
27
|
+
constructor(message, runId) {
|
|
28
|
+
super(message, runId);
|
|
29
|
+
this.name = "Pipe0CanceledError";
|
|
30
|
+
}
|
|
31
|
+
};
|
|
20
32
|
var Pipe0BatchError = class extends Error {
|
|
21
33
|
constructor(message, errors, successfulBatches) {
|
|
22
34
|
super(message);
|
|
@@ -36,11 +48,53 @@ var Pipe0TaskError = class extends Error {
|
|
|
36
48
|
}
|
|
37
49
|
};
|
|
38
50
|
var Pipe0ServerError = class extends Error {
|
|
39
|
-
|
|
51
|
+
/** HTTP status of the error response, when known. */
|
|
52
|
+
status;
|
|
53
|
+
/** RFC 7807 problem `type` discriminator (e.g. "queue-limit-exceeded", "org-rate-limited"). */
|
|
54
|
+
problemType;
|
|
55
|
+
constructor(message, options = {}) {
|
|
40
56
|
super(message);
|
|
41
57
|
this.name = "Pipe0ServerError";
|
|
58
|
+
this.status = options.status;
|
|
59
|
+
this.problemType = options.problemType;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Thrown only after the SDK's automatic 429 handling exhausted its wait
|
|
64
|
+
* budget (`rateLimitMaxWaitMs` / `queueFullMaxWaitMs`), or immediately when
|
|
65
|
+
* `autoRetry429` is disabled the error surfaces as a plain
|
|
66
|
+
* {@link Pipe0ServerError} instead. Subclasses Pipe0ServerError so existing
|
|
67
|
+
* handling keeps working.
|
|
68
|
+
*/
|
|
69
|
+
var Pipe0RateLimitError = class extends Pipe0ServerError {
|
|
70
|
+
/** The delay the SDK would have waited next, in ms. */
|
|
71
|
+
retryAfterMs;
|
|
72
|
+
/** Attempts made before giving up. */
|
|
73
|
+
attempts;
|
|
74
|
+
constructor(message, options = {}) {
|
|
75
|
+
super(message, {
|
|
76
|
+
status: 429,
|
|
77
|
+
problemType: options.problemType
|
|
78
|
+
});
|
|
79
|
+
this.name = "Pipe0RateLimitError";
|
|
80
|
+
this.retryAfterMs = options.retryAfterMs;
|
|
81
|
+
this.attempts = options.attempts ?? 1;
|
|
42
82
|
}
|
|
43
83
|
};
|
|
84
|
+
/** The run-creating endpoints — the only responses that carry capacity headers. */
|
|
85
|
+
const CAPACITY_HEADER_PATHS = new Set([
|
|
86
|
+
"/v1/pipes/run",
|
|
87
|
+
"/v1/pipes/run/sync",
|
|
88
|
+
"/v1/search/run",
|
|
89
|
+
"/v1/search/run/sync",
|
|
90
|
+
"/v1/searches/run",
|
|
91
|
+
"/v1/searches/run/sync",
|
|
92
|
+
"/v1/pipes/cancel/{run_id}",
|
|
93
|
+
"/v1/search/cancel/{run_id}"
|
|
94
|
+
]);
|
|
95
|
+
function extractProblemType(error) {
|
|
96
|
+
if (error !== null && typeof error === "object" && "type" in error && typeof error.type === "string") return error.type;
|
|
97
|
+
}
|
|
44
98
|
var Pipe0 = class {
|
|
45
99
|
client;
|
|
46
100
|
apiKey;
|
|
@@ -49,6 +103,15 @@ var Pipe0 = class {
|
|
|
49
103
|
maxPollingIntervalMs;
|
|
50
104
|
defaultBatchSize;
|
|
51
105
|
maxConcurrentBatches;
|
|
106
|
+
autoRetry429;
|
|
107
|
+
retryAfterCapMs;
|
|
108
|
+
rateLimitMaxWaitMs;
|
|
109
|
+
queueFullMaxWaitMs;
|
|
110
|
+
defaultCancelOnAbort;
|
|
111
|
+
defaultPriorityFloor;
|
|
112
|
+
pacingProbeMs;
|
|
113
|
+
onCapacity;
|
|
114
|
+
tracker = new CapacityTracker();
|
|
52
115
|
constructor(options = {}) {
|
|
53
116
|
const envApiKey = typeof process !== "undefined" ? process.env?.PIPE0_API_KEY : void 0;
|
|
54
117
|
this.apiKey = options.apiKey ?? envApiKey;
|
|
@@ -57,13 +120,92 @@ var Pipe0 = class {
|
|
|
57
120
|
this.maxPollingIntervalMs = options.maxPollingIntervalMs ?? this.minPollingIntervalMs * 3;
|
|
58
121
|
this.defaultBatchSize = options.defaultBatchSize ?? 100;
|
|
59
122
|
this.maxConcurrentBatches = options.maxConcurrentBatches ?? 5;
|
|
123
|
+
this.autoRetry429 = options.autoRetry429 ?? true;
|
|
124
|
+
this.retryAfterCapMs = options.retryAfterCapMs ?? 3e4;
|
|
125
|
+
this.rateLimitMaxWaitMs = options.rateLimitMaxWaitMs ?? 12e4;
|
|
126
|
+
this.queueFullMaxWaitMs = options.queueFullMaxWaitMs ?? 9e5;
|
|
127
|
+
this.defaultCancelOnAbort = options.cancelOnAbort ?? true;
|
|
128
|
+
this.defaultPriorityFloor = options.priorityFloor ?? 2;
|
|
129
|
+
this.pacingProbeMs = options.pacingProbeMs ?? 15e3;
|
|
130
|
+
this.onCapacity = options.onCapacity;
|
|
60
131
|
const headers = {};
|
|
61
132
|
if (this.apiKey) headers.Authorization = `Bearer ${this.apiKey}`;
|
|
62
133
|
this.client = createFetchClient({
|
|
63
134
|
baseUrl: options.baseUrl ?? "https://api.pipe0.com",
|
|
64
135
|
credentials: options.credentials ? options.credentials : options.baseUrl ? "same-origin" : "include",
|
|
65
|
-
headers
|
|
136
|
+
headers,
|
|
137
|
+
fetch: options.fetch
|
|
66
138
|
});
|
|
139
|
+
this.client.use({ onResponse: ({ schemaPath, response }) => {
|
|
140
|
+
if (!CAPACITY_HEADER_PATHS.has(schemaPath)) return void 0;
|
|
141
|
+
const snapshot = this.tracker.observeHeaders(response.headers);
|
|
142
|
+
if (snapshot && this.onCapacity) try {
|
|
143
|
+
this.onCapacity(snapshot);
|
|
144
|
+
} catch {}
|
|
145
|
+
} });
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The SDK's current estimate of your organization's queue capacity, from
|
|
149
|
+
* the most recent run-creating response's headers adjusted by runs the SDK
|
|
150
|
+
* has since observed completing. Null until the first create.
|
|
151
|
+
*/
|
|
152
|
+
get capacity() {
|
|
153
|
+
return this.tracker.snapshot();
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The single request funnel: every API call goes through here so 429
|
|
157
|
+
* handling and capacity bookkeeping live in exactly one place.
|
|
158
|
+
*
|
|
159
|
+
* - `org-rate-limited` (request bucket, has Retry-After): sleep and retry,
|
|
160
|
+
* budget `rateLimitMaxWaitMs`.
|
|
161
|
+
* - `queue-limit-exceeded` (queued-record hard ceiling, no Retry-After):
|
|
162
|
+
* exponential backoff retry, budget `queueFullMaxWaitMs` — re-issuing the
|
|
163
|
+
* create is safe because the ceiling rejects before anything is queued.
|
|
164
|
+
* - Anything else throws {@link Pipe0ServerError} with `status` +
|
|
165
|
+
* `problemType` attached.
|
|
166
|
+
*/
|
|
167
|
+
async request(fn, opts = {}) {
|
|
168
|
+
const retryEnabled = opts.retry ?? this.autoRetry429;
|
|
169
|
+
const startedAt = Date.now();
|
|
170
|
+
let attempts = 0;
|
|
171
|
+
let queueDelayMs = 5e3;
|
|
172
|
+
while (true) {
|
|
173
|
+
attempts += 1;
|
|
174
|
+
if (opts.capacity) this.tracker.onCreateIssued(opts.capacity.records);
|
|
175
|
+
let result;
|
|
176
|
+
try {
|
|
177
|
+
result = await fn();
|
|
178
|
+
} finally {
|
|
179
|
+
if (opts.capacity) this.tracker.onCreateSettled(opts.capacity.records);
|
|
180
|
+
}
|
|
181
|
+
if (!result.error) return result.data;
|
|
182
|
+
const status = result.response?.status;
|
|
183
|
+
const problemType = extractProblemType(result.error);
|
|
184
|
+
if (status !== 429 || !retryEnabled) throw new Pipe0ServerError(JSON.stringify(result.error), {
|
|
185
|
+
status,
|
|
186
|
+
problemType
|
|
187
|
+
});
|
|
188
|
+
const isQueueFull = problemType === "queue-limit-exceeded";
|
|
189
|
+
let delayMs;
|
|
190
|
+
let budgetMs;
|
|
191
|
+
if (isQueueFull) {
|
|
192
|
+
delayMs = queueDelayMs;
|
|
193
|
+
queueDelayMs = Math.min(queueDelayMs * 2, 6e4);
|
|
194
|
+
budgetMs = this.queueFullMaxWaitMs;
|
|
195
|
+
} else {
|
|
196
|
+
const retryAfterSeconds = Number(result.response.headers.get("Retry-After"));
|
|
197
|
+
const baseMs = Number.isFinite(retryAfterSeconds) && retryAfterSeconds > 0 ? retryAfterSeconds * 1e3 : 5e3;
|
|
198
|
+
delayMs = Math.min(Math.max(baseMs, 1e3), this.retryAfterCapMs);
|
|
199
|
+
budgetMs = this.rateLimitMaxWaitMs;
|
|
200
|
+
}
|
|
201
|
+
delayMs = Math.round(delayMs * (1 + Math.random() * .25));
|
|
202
|
+
if (Date.now() - startedAt + delayMs > budgetMs) throw new Pipe0RateLimitError(`Request still rate limited (${problemType ?? "429"}) after ${attempts} attempt(s) over ${Date.now() - startedAt}ms`, {
|
|
203
|
+
problemType,
|
|
204
|
+
retryAfterMs: delayMs,
|
|
205
|
+
attempts
|
|
206
|
+
});
|
|
207
|
+
await this.sleep(delayMs, opts.signal);
|
|
208
|
+
}
|
|
67
209
|
}
|
|
68
210
|
/**
|
|
69
211
|
* Centralized logic to poll until a task completes, fails, or times out.
|
|
@@ -73,107 +215,184 @@ var Pipe0 = class {
|
|
|
73
215
|
const timeout = this.pollingTimeoutMs;
|
|
74
216
|
const initialInterval = this.minPollingIntervalMs;
|
|
75
217
|
const maxInterval = this.maxPollingIntervalMs;
|
|
218
|
+
const cancelOnAbort = options.cancelOnAbort ?? this.defaultCancelOnAbort;
|
|
76
219
|
const startTime = Date.now();
|
|
77
220
|
let currentInterval = initialInterval;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
221
|
+
try {
|
|
222
|
+
while (true) {
|
|
223
|
+
if (Date.now() - startTime >= timeout) throw new Pipe0TimeoutError(`${taskType} polling timed out after ${timeout}ms`, resolvedRunId);
|
|
224
|
+
if (options.signal?.aborted) throw new Pipe0AbortError(`${taskType} polling was aborted`, resolvedRunId);
|
|
225
|
+
const polledResponse = await checkFn(resolvedRunId);
|
|
226
|
+
if (options.onPoll) await options.onPoll(polledResponse);
|
|
227
|
+
if (polledResponse.status === "completed") {
|
|
228
|
+
this.tracker.creditTerminal(resolvedRunId);
|
|
229
|
+
return polledResponse;
|
|
230
|
+
}
|
|
231
|
+
if (polledResponse.status === "skipped") {
|
|
232
|
+
this.tracker.creditTerminal(resolvedRunId);
|
|
233
|
+
return polledResponse;
|
|
234
|
+
}
|
|
235
|
+
if (polledResponse.status === "canceled") {
|
|
236
|
+
this.tracker.creditTerminal(resolvedRunId);
|
|
237
|
+
throw new Pipe0CanceledError(`${taskType} run was canceled`, resolvedRunId);
|
|
238
|
+
}
|
|
239
|
+
if (polledResponse.status === "failed") {
|
|
240
|
+
this.tracker.creditTerminal(resolvedRunId);
|
|
241
|
+
throw new Pipe0TaskError(`${taskType} failed with status: ${polledResponse.status}`, polledResponse);
|
|
242
|
+
}
|
|
243
|
+
await this.sleep(currentInterval, options.signal);
|
|
244
|
+
currentInterval = Math.min(currentInterval * 1.1, maxInterval);
|
|
245
|
+
}
|
|
246
|
+
} catch (error) {
|
|
247
|
+
if (cancelOnAbort && options.cancelFn && options.signal?.aborted && !(error instanceof Pipe0CanceledError)) options.cancelFn(resolvedRunId).catch(() => {});
|
|
248
|
+
throw error;
|
|
89
249
|
}
|
|
90
250
|
}
|
|
91
251
|
pipes = {
|
|
92
252
|
pipe: async (payload, options = {}) => {
|
|
93
|
-
return this.pipes.waitUntilComplete(await this.pipes.create(payload), options);
|
|
253
|
+
return this.pipes.waitUntilComplete(await this.pipes.create(payload, options), options);
|
|
254
|
+
},
|
|
255
|
+
create: async (payload, options = {}) => {
|
|
256
|
+
const records = Array.isArray(payload.input) ? payload.input.length : 1;
|
|
257
|
+
const data = await this.request(() => this.client.POST("/v1/pipes/run", { body: payload }), {
|
|
258
|
+
signal: options.signal,
|
|
259
|
+
capacity: { records }
|
|
260
|
+
});
|
|
261
|
+
this.tracker.registerRun(data.id, records);
|
|
262
|
+
return data.id;
|
|
94
263
|
},
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
264
|
+
check: async (runId, options = {}) => {
|
|
265
|
+
return this.request(() => this.client.GET("/v1/pipes/check/{run_id}", {
|
|
266
|
+
params: { path: { run_id: runId } },
|
|
267
|
+
signal: options.signal
|
|
268
|
+
}), { signal: options.signal });
|
|
99
269
|
},
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
270
|
+
cancel: async (runId, options = {}) => {
|
|
271
|
+
const data = await this.request(() => this.client.POST("/v1/pipes/cancel/{run_id}", {
|
|
272
|
+
params: { path: { run_id: runId } },
|
|
273
|
+
signal: options.signal
|
|
274
|
+
}), { signal: options.signal });
|
|
275
|
+
this.tracker.creditTerminal(runId);
|
|
276
|
+
return data;
|
|
104
277
|
},
|
|
105
278
|
waitUntilComplete: async (runId, options = {}) => {
|
|
106
|
-
return this._pollUntilComplete(runId, this.pipes.check, "Pipe",
|
|
279
|
+
return this._pollUntilComplete(runId, (id) => this.pipes.check(id, { signal: options.signal }), "Pipe", {
|
|
280
|
+
...options,
|
|
281
|
+
cancelFn: (id) => this.pipes.cancel(id)
|
|
282
|
+
});
|
|
107
283
|
},
|
|
108
|
-
pipeInBatches: async (payload, { stopOnError = true, ...options } = {}) => {
|
|
284
|
+
pipeInBatches: async (payload, { stopOnError = true, priorityFloor, cancelOnAbort, ...options } = {}) => {
|
|
109
285
|
const batchSize = this.defaultBatchSize;
|
|
110
286
|
const maxConcurrency = this.maxConcurrentBatches;
|
|
287
|
+
const floor = priorityFloor ?? this.defaultPriorityFloor;
|
|
288
|
+
const doCancelOnAbort = cancelOnAbort ?? this.defaultCancelOnAbort;
|
|
111
289
|
if (!Array.isArray(payload.input)) throw new Error("payload.input must be an array for batched operations");
|
|
112
290
|
const inputArray = payload.input;
|
|
113
|
-
const totalItems = inputArray.length;
|
|
114
291
|
const batches = [];
|
|
115
|
-
for (let i = 0; i <
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
const resultsArr = [];
|
|
292
|
+
for (let i = 0; i < inputArray.length; i += batchSize) batches.push({
|
|
293
|
+
...payload,
|
|
294
|
+
input: inputArray.slice(i, i + batchSize)
|
|
295
|
+
});
|
|
296
|
+
const results = new Array(batches.length);
|
|
123
297
|
const errors = [];
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
298
|
+
const inFlight = /* @__PURE__ */ new Set();
|
|
299
|
+
/** batchIndex → runId while the run is still cancelable. */
|
|
300
|
+
const pendingRuns = /* @__PURE__ */ new Map();
|
|
301
|
+
let next = 0;
|
|
302
|
+
let stopped = false;
|
|
303
|
+
const sweepCancel = () => {
|
|
304
|
+
if (!doCancelOnAbort) return;
|
|
305
|
+
for (const runId of pendingRuns.values()) this.pipes.cancel(runId).catch(() => {});
|
|
306
|
+
pendingRuns.clear();
|
|
307
|
+
};
|
|
308
|
+
const runBatch = async (batchIndex) => {
|
|
309
|
+
try {
|
|
310
|
+
const runId = await this.pipes.create(batches[batchIndex], { signal: options.signal });
|
|
311
|
+
pendingRuns.set(batchIndex, runId);
|
|
312
|
+
const result = await this.pipes.waitUntilComplete(runId, {
|
|
313
|
+
signal: options.signal,
|
|
314
|
+
cancelOnAbort: false,
|
|
315
|
+
onPoll: options.onPoll ? (response) => options.onPoll(batchIndex, response) : void 0
|
|
316
|
+
});
|
|
317
|
+
pendingRuns.delete(batchIndex);
|
|
318
|
+
results[batchIndex] = result;
|
|
319
|
+
if (options.onBatchComplete) options.onBatchComplete(batchIndex, result);
|
|
320
|
+
} catch (error) {
|
|
321
|
+
if (error instanceof Pipe0AbortError && options.signal?.aborted) return;
|
|
322
|
+
pendingRuns.delete(batchIndex);
|
|
323
|
+
errors.push({
|
|
324
|
+
batchIndex,
|
|
325
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
326
|
+
});
|
|
327
|
+
if (stopOnError) stopped = true;
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
const submit = (batchIndex) => {
|
|
331
|
+
const p = runBatch(batchIndex).finally(() => inFlight.delete(p));
|
|
332
|
+
inFlight.add(p);
|
|
333
|
+
};
|
|
334
|
+
try {
|
|
335
|
+
while (next < batches.length && !stopped || inFlight.size > 0) {
|
|
336
|
+
if (options.signal?.aborted) throw new Pipe0AbortError("Batch operation was aborted");
|
|
337
|
+
if (!stopped && next < batches.length && inFlight.size < maxConcurrency) {
|
|
338
|
+
const records = batches[next].input.length;
|
|
339
|
+
const estimate = this.tracker.estimate(floor);
|
|
340
|
+
if (estimate === null || estimate >= records) {
|
|
341
|
+
submit(next++);
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
if (inFlight.size === 0) {
|
|
345
|
+
await this.sleep(this.pacingProbeMs, options.signal);
|
|
346
|
+
if (options.signal?.aborted) throw new Pipe0AbortError("Batch operation was aborted");
|
|
347
|
+
submit(next++);
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
150
350
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
351
|
+
if (inFlight.size > 0) await Promise.race(inFlight);
|
|
352
|
+
}
|
|
353
|
+
} catch (error) {
|
|
354
|
+
sweepCancel();
|
|
355
|
+
throw error;
|
|
154
356
|
}
|
|
155
|
-
|
|
156
|
-
|
|
357
|
+
const compact = results.filter((r) => r !== void 0);
|
|
358
|
+
if (stopped) throw new Pipe0BatchError(`Batch ${errors[0]?.batchIndex} failed and stopOnError is enabled`, errors, compact);
|
|
359
|
+
if (errors.length > 0) throw new Pipe0BatchError(`${errors.length} batch(es) failed out of ${batches.length} total`, errors, compact);
|
|
360
|
+
return compact;
|
|
157
361
|
}
|
|
158
362
|
};
|
|
159
363
|
searches = {
|
|
160
364
|
search: async (payload, options = {}) => {
|
|
161
|
-
return this.searches.waitUntilComplete(await this.searches.create(payload), options);
|
|
365
|
+
return this.searches.waitUntilComplete(await this.searches.create(payload, options), options);
|
|
366
|
+
},
|
|
367
|
+
create: async (payload, options = {}) => {
|
|
368
|
+
const data = await this.request(() => this.client.POST("/v1/search/run", { body: payload }), {
|
|
369
|
+
signal: options.signal,
|
|
370
|
+
capacity: { records: 1 }
|
|
371
|
+
});
|
|
372
|
+
this.tracker.registerRun(data.id, 1);
|
|
373
|
+
return data.id;
|
|
162
374
|
},
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
375
|
+
check: async (runId, options = {}) => {
|
|
376
|
+
return this.request(() => this.client.GET("/v1/search/check/{run_id}", {
|
|
377
|
+
params: { path: { run_id: runId } },
|
|
378
|
+
signal: options.signal
|
|
379
|
+
}), { signal: options.signal });
|
|
167
380
|
},
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
381
|
+
cancel: async (runId, options = {}) => {
|
|
382
|
+
const data = await this.request(() => this.client.POST("/v1/search/cancel/{run_id}", {
|
|
383
|
+
params: { path: { run_id: runId } },
|
|
384
|
+
signal: options.signal
|
|
385
|
+
}), { signal: options.signal });
|
|
386
|
+
this.tracker.creditTerminal(runId);
|
|
387
|
+
return data;
|
|
172
388
|
},
|
|
173
389
|
waitUntilComplete: async (runId, options = {}) => {
|
|
174
|
-
return this._pollUntilComplete(runId, this.searches.check, "Search",
|
|
390
|
+
return this._pollUntilComplete(runId, (id) => this.searches.check(id, { signal: options.signal }), "Search", {
|
|
391
|
+
...options,
|
|
392
|
+
cancelFn: (id) => this.searches.cancel(id)
|
|
393
|
+
});
|
|
175
394
|
},
|
|
176
|
-
searchAll: async ({ searches, config, dedupeBy, maxPages = 1, normalize = true, maxConcurrency = this.maxConcurrentBatches, signal, stopOnError = true }) => {
|
|
395
|
+
searchAll: async ({ searches, config, dedupeBy, maxPages = 1, normalize = true, maxConcurrency = this.maxConcurrentBatches, signal, stopOnError = true, cancelOnAbort }) => {
|
|
177
396
|
const errors = [];
|
|
178
397
|
const merged = [];
|
|
179
398
|
const runItem = async (item) => {
|
|
@@ -185,7 +404,10 @@ var Pipe0 = class {
|
|
|
185
404
|
const res = await this.searches.search({
|
|
186
405
|
config,
|
|
187
406
|
search
|
|
188
|
-
}, {
|
|
407
|
+
}, {
|
|
408
|
+
signal,
|
|
409
|
+
cancelOnAbort
|
|
410
|
+
});
|
|
189
411
|
rows.push(...res.results);
|
|
190
412
|
const next = res.next_page;
|
|
191
413
|
if (!next) break;
|
|
@@ -220,23 +442,22 @@ var Pipe0 = class {
|
|
|
220
442
|
};
|
|
221
443
|
sheets = { effects: {
|
|
222
444
|
run: async (sheetId, payload) => {
|
|
223
|
-
|
|
445
|
+
return this.request(() => this.client.POST("/v1/sheets/{sheet_id}/effects/run", {
|
|
224
446
|
params: { path: { sheet_id: sheetId } },
|
|
225
447
|
body: payload
|
|
226
|
-
});
|
|
227
|
-
if (response.error) throw new Pipe0ServerError(JSON.stringify(response.error));
|
|
228
|
-
return response.data;
|
|
448
|
+
}));
|
|
229
449
|
},
|
|
230
|
-
check: async (sheetId, runId) => {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
450
|
+
check: async (sheetId, runId, options = {}) => {
|
|
451
|
+
return this.request(() => this.client.GET("/v1/sheets/{sheet_id}/effects/check/{run_id}", {
|
|
452
|
+
params: { path: {
|
|
453
|
+
sheet_id: sheetId,
|
|
454
|
+
run_id: runId
|
|
455
|
+
} },
|
|
456
|
+
signal: options.signal
|
|
457
|
+
}), { signal: options.signal });
|
|
237
458
|
},
|
|
238
459
|
waitUntilComplete: async (sheetId, runId, options = {}) => {
|
|
239
|
-
return this._pollUntilComplete(runId, (id) => this.sheets.effects.check(sheetId, id), "Effects", options);
|
|
460
|
+
return this._pollUntilComplete(runId, (id) => this.sheets.effects.check(sheetId, id, { signal: options.signal }), "Effects", options);
|
|
240
461
|
},
|
|
241
462
|
runUntilComplete: async (sheetId, payload, options = {}) => {
|
|
242
463
|
const { id } = await this.sheets.effects.run(sheetId, payload);
|
|
@@ -284,7 +505,7 @@ function dedupeResults(rows, fields) {
|
|
|
284
505
|
out.push(row);
|
|
285
506
|
continue;
|
|
286
507
|
}
|
|
287
|
-
const key = parts.join("
|
|
508
|
+
const key = parts.join(" ");
|
|
288
509
|
if (seen.has(key)) continue;
|
|
289
510
|
seen.add(key);
|
|
290
511
|
out.push(row);
|
|
@@ -308,5 +529,5 @@ function normalizeResults(rows) {
|
|
|
308
529
|
}
|
|
309
530
|
|
|
310
531
|
//#endregion
|
|
311
|
-
export { Pipe0, Pipe0AbortError, Pipe0BatchError, Pipe0ServerError, Pipe0TaskError, Pipe0TimeoutError };
|
|
532
|
+
export { Pipe0, Pipe0AbortError, Pipe0BatchError, Pipe0CanceledError, Pipe0RateLimitError, Pipe0ServerError, Pipe0TaskError, Pipe0TimeoutError };
|
|
312
533
|
//# sourceMappingURL=pipe0.mjs.map
|