|
1 | 1 | import Path from 'node:path'; |
2 | | -import { fetch, FormData } from 'undici'; |
| 2 | +import { fetch, FormData, Agent } from 'undici'; |
3 | 3 | // eslint-disable-next-line n/no-unsupported-features/node-builtins |
4 | 4 | import { Blob } from 'node:buffer'; |
5 | 5 | import { Config, EdgeImpulseConfig } from './config'; |
@@ -165,40 +165,89 @@ export async function upload(opts: { |
165 | 165 | }), 'label_map.labels'); |
166 | 166 | } |
167 | 167 |
|
168 | | - let res = await fetch(opts.config.endpoints.internal.ingestion + '/api/' + category + '/files', { |
169 | | - method: 'POST', |
170 | | - headers: headers, |
171 | | - body: form, |
172 | | - }); |
173 | | - |
174 | | - let body = await res.text(); |
175 | | - let msg: ({ success: false, error: string } | |
176 | | - { success: true, files: ({ success: false, error: string } | { success: true })[]}) | undefined; |
| 168 | + const url = opts.config.endpoints.internal.ingestion + '/api/' + category + '/files'; |
177 | 169 | try { |
178 | | - msg = <{ success: false, error: string } | |
179 | | - { success: true, files: ({ success: false, error: string } | { success: true })[]}>JSON.parse(body); |
180 | | - } |
181 | | - catch (ex2) { |
182 | | - // noop |
183 | | - } |
| 170 | + let res = await fetch(url, { |
| 171 | + method: 'POST', |
| 172 | + headers: headers, |
| 173 | + body: form, |
| 174 | + dispatcher: new Agent({ |
| 175 | + headersTimeout: 20 * 60_000, |
| 176 | + bodyTimeout: 20 * 60_000, |
| 177 | + }), |
| 178 | + }); |
| 179 | + |
| 180 | + let body = await res.text(); |
| 181 | + let msg: ({ success: false, error: string } | |
| 182 | + { success: true, files: ({ success: false, error: string } | { success: true })[]}) | undefined; |
| 183 | + try { |
| 184 | + msg = <{ success: false, error: string } | |
| 185 | + { success: true, files: ({ success: false, error: string } | { success: true })[]}>JSON.parse(body); |
| 186 | + } |
| 187 | + catch (ex2) { |
| 188 | + // noop |
| 189 | + } |
184 | 190 |
|
185 | | - if (res.status !== 200) { |
186 | | - if (msg && msg.success === false) { |
| 191 | + if (res.status !== 200) { |
| 192 | + if (msg && msg.success === false) { |
| 193 | + throw new Error(msg.error); |
| 194 | + } |
| 195 | + throw new Error(body || res.status.toString()); |
| 196 | + } |
| 197 | + |
| 198 | + if (!msg) { |
| 199 | + throw new Error('Ingestion returned 200, but body is not a valid response message: ' + |
| 200 | + body); |
| 201 | + } |
| 202 | + if (!msg.success) { |
187 | 203 | throw new Error(msg.error); |
188 | 204 | } |
189 | | - throw new Error(body || res.status.toString()); |
| 205 | + for (let f of msg.files) { |
| 206 | + if (!f.success) { |
| 207 | + throw new Error(f.error); |
| 208 | + } |
| 209 | + } |
190 | 210 | } |
191 | | - |
192 | | - if (!msg) { |
193 | | - throw new Error('Ingestion returned 200, but body is not a valid response message: ' + |
194 | | - body); |
| 211 | + catch (ex) { |
| 212 | + throw new Error(formatFetchError(url, ex)); |
195 | 213 | } |
196 | | - if (!msg.success) { |
197 | | - throw new Error(msg.error); |
| 214 | +} |
| 215 | + |
| 216 | +function formatFetchError(url: string, err: unknown): string { |
| 217 | + type ErrorWithCause = Error & { |
| 218 | + cause?: unknown; |
| 219 | + }; |
| 220 | + |
| 221 | + type ErrorCause = { |
| 222 | + name?: string; |
| 223 | + message?: string; |
| 224 | + code?: string; |
| 225 | + errno?: number; |
| 226 | + syscall?: string; |
| 227 | + hostname?: string; |
| 228 | + address?: string; |
| 229 | + port?: number; |
| 230 | + }; |
| 231 | + |
| 232 | + if (!(err instanceof Error)) { |
| 233 | + return String(err); |
198 | 234 | } |
199 | | - for (let f of msg.files) { |
200 | | - if (!f.success) { |
201 | | - throw new Error(f.error); |
202 | | - } |
| 235 | + |
| 236 | + if ((err as ErrorWithCause).cause) { |
| 237 | + const cause = <ErrorCause>(<ErrorWithCause>err).cause; |
| 238 | + const msg = [ |
| 239 | + `${err.name}: ${err.message}`, |
| 240 | + cause ? `cause: ${cause.name ?? 'Error'}${cause.message ? ` (${cause.message})` : ``}` : undefined, |
| 241 | + cause?.code ? `code: ${cause.code}` : undefined, |
| 242 | + cause?.errno !== undefined ? `errno: ${cause.errno}` : undefined, |
| 243 | + cause?.syscall ? `syscall: ${cause.syscall}` : undefined, |
| 244 | + cause?.hostname ? `hostname: ${cause.hostname}` : undefined, |
| 245 | + cause?.address ? `address: ${cause.address}` : undefined, |
| 246 | + cause?.port ? `port: ${cause.port}` : undefined, |
| 247 | + ].filter(x => !!x).join(', '); |
| 248 | + |
| 249 | + return `Request to ${url} failed: ${msg}`; |
203 | 250 | } |
| 251 | + |
| 252 | + return `Request to ${url} failed: ${err.message || err.toString()}`; |
204 | 253 | } |
0 commit comments