@ultimat3/scraping 31.4.0 → 31.4.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/package.json +6 -6
- package/src/cdp-connection.ts +9 -2
- package/src/cdp-launch-wire.ts +6 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/scraping",
|
|
3
|
-
"version": "31.4.
|
|
3
|
+
"version": "31.4.2",
|
|
4
4
|
"description": "Browser automation as a job: scrape() returns a JobHandle",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ultimate",
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
"test": "bun test"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@ultimat3/action": "31.4.
|
|
47
|
-
"@ultimat3/core": "31.4.
|
|
48
|
-
"@ultimat3/jobs": "31.4.
|
|
49
|
-
"@ultimat3/schema": "31.4.
|
|
50
|
-
"@ultimat3/storage": "31.4.
|
|
46
|
+
"@ultimat3/action": "31.4.2",
|
|
47
|
+
"@ultimat3/core": "31.4.2",
|
|
48
|
+
"@ultimat3/jobs": "31.4.2",
|
|
49
|
+
"@ultimat3/schema": "31.4.2",
|
|
50
|
+
"@ultimat3/storage": "31.4.2"
|
|
51
51
|
}
|
|
52
52
|
}
|
package/src/cdp-connection.ts
CHANGED
|
@@ -96,6 +96,12 @@ export interface CdpConnectionOptions {
|
|
|
96
96
|
readonly endpoint: string;
|
|
97
97
|
/** Per-call deadline. A CDP call that never answers is a suite that never finishes. */
|
|
98
98
|
readonly timeoutMs: number;
|
|
99
|
+
/**
|
|
100
|
+
* The handshake's deadline, when it is not a call's: a launcher dials a browser that is still
|
|
101
|
+
* starting, inside what is left of its LAUNCH deadline (`cdp-launch-wire.ts`). `timeoutMs` if
|
|
102
|
+
* unset.
|
|
103
|
+
*/
|
|
104
|
+
readonly connectTimeoutMs?: number | undefined;
|
|
99
105
|
}
|
|
100
106
|
|
|
101
107
|
/**
|
|
@@ -120,14 +126,15 @@ export async function cdpConnect(options: CdpConnectionOptions): Promise<CdpConn
|
|
|
120
126
|
`the CDP endpoint is ${options.endpoint === '' ? 'empty' : 'not a WebSocket url'}`,
|
|
121
127
|
'pass the `webSocketDebuggerUrl` Chrome prints on stderr, or the one /json/version answers',
|
|
122
128
|
);
|
|
129
|
+
const connectTimeoutMs = options.connectTimeoutMs ?? options.timeoutMs;
|
|
123
130
|
const socket = new WebSocket(options.endpoint);
|
|
124
131
|
await new Promise<void>((resolve, reject) => {
|
|
125
132
|
// The socket is CLOSED on both failures: a handshake that timed out otherwise kept dialling
|
|
126
133
|
// in the background, holding a descriptor and a pending connection for a caller that gave up.
|
|
127
134
|
const timer = setTimeout(() => {
|
|
128
135
|
socket.close();
|
|
129
|
-
reject(new CdpTimeoutError({ method: 'connect', timeoutMs:
|
|
130
|
-
},
|
|
136
|
+
reject(new CdpTimeoutError({ method: 'connect', timeoutMs: connectTimeoutMs }));
|
|
137
|
+
}, connectTimeoutMs);
|
|
131
138
|
socket.onopen = (): void => {
|
|
132
139
|
clearTimeout(timer);
|
|
133
140
|
resolve();
|
package/src/cdp-launch-wire.ts
CHANGED
|
@@ -68,27 +68,20 @@ export function devToolsEndpoint(text: string): string | undefined {
|
|
|
68
68
|
const ANNOUNCE_POLL_MS = 25;
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
|
-
* Dial, inside what is left of the LAUNCH deadline
|
|
72
|
-
* the connection keeps afterwards,
|
|
73
|
-
*
|
|
71
|
+
* Dial, inside what is left of the LAUNCH deadline. The handshake gets `leftMs`; `timeoutMs` is the
|
|
72
|
+
* per-call deadline the connection keeps afterwards, and it was the handshake's too until windows
|
|
73
|
+
* CI (run 42978963381) gave up on a cold Chrome 10 s into the upgrade with 50 s of its launch left —
|
|
74
|
+
* a browser that has bound its port is still starting, not dead. `cdpConnect` closes a socket whose
|
|
75
|
+
* handshake ran out, so a late upgrade never holds a socket nobody reads.
|
|
74
76
|
*/
|
|
75
77
|
async function dialWithin(
|
|
76
78
|
endpoint: string,
|
|
77
79
|
leftMs: number,
|
|
78
80
|
timeoutMs: number,
|
|
79
81
|
): Promise<CdpConnection> {
|
|
80
|
-
const dialing = cdpConnect({ endpoint, timeoutMs });
|
|
81
|
-
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
82
|
-
const late = new Promise<never>((_, reject) => {
|
|
83
|
-
timer = setTimeout(
|
|
84
|
-
() => reject(new CdpTimeoutError({ method: 'connect', timeoutMs: leftMs })),
|
|
85
|
-
leftMs,
|
|
86
|
-
);
|
|
87
|
-
});
|
|
88
82
|
try {
|
|
89
|
-
return await
|
|
83
|
+
return await cdpConnect({ endpoint, timeoutMs, connectTimeoutMs: leftMs });
|
|
90
84
|
} catch (error) {
|
|
91
|
-
void dialing.then((connection) => connection.close()).catch(() => undefined);
|
|
92
85
|
// A timeout stays one — the launcher reads it as the deadline. Any other refusal names the
|
|
93
86
|
// endpoint it was for: the browser announced it, so the dial is the step that failed.
|
|
94
87
|
if (error instanceof CdpTimeoutError) throw error;
|
|
@@ -96,8 +89,6 @@ async function dialWithin(
|
|
|
96
89
|
method: `connect ${endpoint}`,
|
|
97
90
|
detail: renderThrowable(error),
|
|
98
91
|
});
|
|
99
|
-
} finally {
|
|
100
|
-
clearTimeout(timer);
|
|
101
92
|
}
|
|
102
93
|
}
|
|
103
94
|
|