gecko-web-runtime-client 1.2.0__tar.gz → 1.3.0__tar.gz
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.
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/PKG-INFO +28 -16
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/README.md +27 -15
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/installer.py +3 -3
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/network/client.py +5 -5
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime_client.egg-info/PKG-INFO +28 -16
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/pyproject.toml +1 -1
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/__init__.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/__main__.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/_leases.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/api/__init__.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/api/context.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/api/page.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/api/pool.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/api/runtime.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/data_plane.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/diagnostics/__init__.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/diagnostics/gc_cc.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/diagnostics/logging.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/diagnostics/memory.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/diagnostics/metrics.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/diagnostics/resources.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/http.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/iocp_pipe.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/models/__init__.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/models/navigation.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/network/__init__.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/network/_urls.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/network/exceptions.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/network/models.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/network/transport.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/pipe.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/session.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/workflows/__init__.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/workflows/turnstile.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/workflows/wechat.py +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime_client.egg-info/SOURCES.txt +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime_client.egg-info/dependency_links.txt +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime_client.egg-info/requires.txt +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime_client.egg-info/top_level.txt +0 -0
- {gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gecko-web-runtime-client
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Thin Python client for the Firefox-derived WPR Gecko Worker protocol
|
|
5
5
|
Author: WPR project
|
|
6
6
|
License: MPL-2.0-compatible client; see the runtime bundle notices
|
|
@@ -11,6 +11,12 @@ Requires-Dist: loguru>=0.7.2; extra == "diagnostics"
|
|
|
11
11
|
|
|
12
12
|
# Python client
|
|
13
13
|
|
|
14
|
+
Version `1.3.0` defaults to one Worker, 20 Channels,
|
|
15
|
+
`ipc_backend="iocp"` and `release_mode="piggyback"`. Published version 1.2.0
|
|
16
|
+
still defaults to one Channel, threaded IPC and immediate release. Runtime
|
|
17
|
+
155.0.5 is required for the new defaults. Existing 1.2.0 installations keep
|
|
18
|
+
their behavior until explicitly upgraded.
|
|
19
|
+
|
|
14
20
|
The client provides a standard-library core plus an optional Loguru-backed
|
|
15
21
|
diagnostics layer. From this directory:
|
|
16
22
|
|
|
@@ -66,16 +72,17 @@ helpers), `network/transport.py` (the versioned Worker boundary),
|
|
|
66
72
|
|
|
67
73
|
`timeout` accepts seconds, `Timeout(total=seconds, pool=seconds)`, or `None`.
|
|
68
74
|
`total` covers queueing plus the active request; `pool` can bound waiting for
|
|
69
|
-
an available
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
an available request slot. The 1.3.0 default is one Worker with 20
|
|
76
|
+
concurrent Channels. `asyncio.gather()` submits the work; the client limits
|
|
77
|
+
active requests to `max_workers * max_channels_per_worker`. No arguments are
|
|
78
|
+
needed to discover the installed runtime and enable the default transport:
|
|
72
79
|
|
|
73
80
|
```python
|
|
74
81
|
import asyncio
|
|
75
82
|
from gecko_web_runtime import AsyncWprHttpClient
|
|
76
83
|
|
|
77
84
|
async def main():
|
|
78
|
-
async with AsyncWprHttpClient(
|
|
85
|
+
async with AsyncWprHttpClient() as client:
|
|
79
86
|
responses = await asyncio.gather(
|
|
80
87
|
*(client.get(f"https://example.com/api/{i}") for i in range(8))
|
|
81
88
|
)
|
|
@@ -87,8 +94,8 @@ async def main():
|
|
|
87
94
|
asyncio.run(main())
|
|
88
95
|
```
|
|
89
96
|
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
Channels bound in-flight requests, not HTTP sockets or Python threads. Set
|
|
98
|
+
`max_channels_per_worker` to change the single-Worker limit. Each extra
|
|
92
99
|
Worker is a separate Firefox process/profile and therefore has its own Gecko
|
|
93
100
|
CookieService state; multi-Worker cookie continuity is not shared or ordered.
|
|
94
101
|
Keep the default `max_workers=1` when requests depend on a single browser cookie
|
|
@@ -96,12 +103,14 @@ jar or when minimizing memory is more important than parallel throughput. The
|
|
|
96
103
|
pool grows lazily up to the configured cap and reuses Workers after requests.
|
|
97
104
|
For latency-sensitive bursts, call `await client.warmup(url)` immediately after
|
|
98
105
|
entering the client and before sending application requests. It starts the
|
|
99
|
-
remaining Workers and makes one full GET per
|
|
106
|
+
remaining Workers and makes one full GET per Channel slot to the supplied URL; the
|
|
100
107
|
responses are read and released while the Worker connections stay open. This
|
|
101
108
|
is real traffic, so use a safe, idempotent endpoint. Cookies set by that
|
|
102
|
-
endpoint remain isolated in each Worker profile.
|
|
103
|
-
|
|
104
|
-
|
|
109
|
+
endpoint remain isolated in each Worker profile. With the new defaults a
|
|
110
|
+
warmup call makes 20 real GETs; entering a client by itself makes none.
|
|
111
|
+
Active timeout/cancellation in the default multiplexed mode cancels only its
|
|
112
|
+
request Channel. Explicit legacy single-Channel mode stops the Worker and
|
|
113
|
+
the next request replaces it.
|
|
105
114
|
A queued request timeout leaves active requests and Workers untouched.
|
|
106
115
|
Connect/read/write phase timeouts still need native Worker support.
|
|
107
116
|
|
|
@@ -127,8 +136,9 @@ completes. Set `WPR_RUNTIME_HOME`, `WPR_RUNTIME_DIR`, and
|
|
|
127
136
|
|
|
128
137
|
Client 1.2.0 with runtime 155.0.5 supports `ipc_backend="iocp"` and
|
|
129
138
|
`max_channels_per_worker=10` with `max_workers=1`, keeping one shared
|
|
130
|
-
cookie/proxy session while issuing concurrent Necko requests.
|
|
131
|
-
|
|
139
|
+
cookie/proxy session while issuing concurrent Necko requests. Version 1.2.0
|
|
140
|
+
uses explicit opt-in; version 1.3.0 selects these features by default.
|
|
141
|
+
Older runtimes lack these capabilities;
|
|
132
142
|
upgrade both the client and runtime before enabling multi-Channel requests.
|
|
133
143
|
See [selection, protocol, and reproducible build instructions](../source/gecko-net-worker/experiments/multiplex-network/README.md).
|
|
134
144
|
|
|
@@ -151,7 +161,8 @@ exact instantaneous maxima, or a claim of equivalent physical RAM consumption.
|
|
|
151
161
|
See [results, limitations, and reproduction commands](tests/results/http-resource-comparison-20261011.md).
|
|
152
162
|
The test entry points are `tests/integration/baidu_live_ab.py` and
|
|
153
163
|
`tests/integration/baidu_resource_ab.py`. They remain development tests; the
|
|
154
|
-
|
|
164
|
+
measurements refer to the released 1.2.0 configuration, not a claim that
|
|
165
|
+
the 1.3.0 defaults have identical resource costs.
|
|
155
166
|
|
|
156
167
|
## Network IPC diagnostics and pipe A/B
|
|
157
168
|
|
|
@@ -222,7 +233,7 @@ $env:WPR_PIPE_MODE = 'persistent'
|
|
|
222
233
|
```
|
|
223
234
|
|
|
224
235
|
```python
|
|
225
|
-
async with AsyncWprHttpClient(
|
|
236
|
+
async with AsyncWprHttpClient() as client:
|
|
226
237
|
response = await client.get("http://127.0.0.1:8080/")
|
|
227
238
|
body = await response.aread()
|
|
228
239
|
await client.flush_releases() # Optional explicit Worker-side confirmation.
|
|
@@ -236,7 +247,8 @@ pipe occupancy can delay it. Thresholds of 32 entries or 8 MiB trigger drains;
|
|
|
236
247
|
they are not global caps on unread response memory. Only acknowledged entries
|
|
237
248
|
are removed from the pending queue. Abort stops the Worker and discards its queue.
|
|
238
249
|
|
|
239
|
-
The default
|
|
250
|
+
The 1.3.0 default is `release_mode="piggyback"`; pass `"immediate"`
|
|
251
|
+
explicitly to release each response through a separate RPC. Old Workers are rejected during
|
|
240
252
|
capability negotiation if piggyback mode is requested, before any HTTP request
|
|
241
253
|
is sent. `transport_stats` covers the currently resident pool, not retired Workers.
|
|
242
254
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Python client
|
|
2
2
|
|
|
3
|
+
Version `1.3.0` defaults to one Worker, 20 Channels,
|
|
4
|
+
`ipc_backend="iocp"` and `release_mode="piggyback"`. Published version 1.2.0
|
|
5
|
+
still defaults to one Channel, threaded IPC and immediate release. Runtime
|
|
6
|
+
155.0.5 is required for the new defaults. Existing 1.2.0 installations keep
|
|
7
|
+
their behavior until explicitly upgraded.
|
|
8
|
+
|
|
3
9
|
The client provides a standard-library core plus an optional Loguru-backed
|
|
4
10
|
diagnostics layer. From this directory:
|
|
5
11
|
|
|
@@ -55,16 +61,17 @@ helpers), `network/transport.py` (the versioned Worker boundary),
|
|
|
55
61
|
|
|
56
62
|
`timeout` accepts seconds, `Timeout(total=seconds, pool=seconds)`, or `None`.
|
|
57
63
|
`total` covers queueing plus the active request; `pool` can bound waiting for
|
|
58
|
-
an available
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
an available request slot. The 1.3.0 default is one Worker with 20
|
|
65
|
+
concurrent Channels. `asyncio.gather()` submits the work; the client limits
|
|
66
|
+
active requests to `max_workers * max_channels_per_worker`. No arguments are
|
|
67
|
+
needed to discover the installed runtime and enable the default transport:
|
|
61
68
|
|
|
62
69
|
```python
|
|
63
70
|
import asyncio
|
|
64
71
|
from gecko_web_runtime import AsyncWprHttpClient
|
|
65
72
|
|
|
66
73
|
async def main():
|
|
67
|
-
async with AsyncWprHttpClient(
|
|
74
|
+
async with AsyncWprHttpClient() as client:
|
|
68
75
|
responses = await asyncio.gather(
|
|
69
76
|
*(client.get(f"https://example.com/api/{i}") for i in range(8))
|
|
70
77
|
)
|
|
@@ -76,8 +83,8 @@ async def main():
|
|
|
76
83
|
asyncio.run(main())
|
|
77
84
|
```
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
Channels bound in-flight requests, not HTTP sockets or Python threads. Set
|
|
87
|
+
`max_channels_per_worker` to change the single-Worker limit. Each extra
|
|
81
88
|
Worker is a separate Firefox process/profile and therefore has its own Gecko
|
|
82
89
|
CookieService state; multi-Worker cookie continuity is not shared or ordered.
|
|
83
90
|
Keep the default `max_workers=1` when requests depend on a single browser cookie
|
|
@@ -85,12 +92,14 @@ jar or when minimizing memory is more important than parallel throughput. The
|
|
|
85
92
|
pool grows lazily up to the configured cap and reuses Workers after requests.
|
|
86
93
|
For latency-sensitive bursts, call `await client.warmup(url)` immediately after
|
|
87
94
|
entering the client and before sending application requests. It starts the
|
|
88
|
-
remaining Workers and makes one full GET per
|
|
95
|
+
remaining Workers and makes one full GET per Channel slot to the supplied URL; the
|
|
89
96
|
responses are read and released while the Worker connections stay open. This
|
|
90
97
|
is real traffic, so use a safe, idempotent endpoint. Cookies set by that
|
|
91
|
-
endpoint remain isolated in each Worker profile.
|
|
92
|
-
|
|
93
|
-
|
|
98
|
+
endpoint remain isolated in each Worker profile. With the new defaults a
|
|
99
|
+
warmup call makes 20 real GETs; entering a client by itself makes none.
|
|
100
|
+
Active timeout/cancellation in the default multiplexed mode cancels only its
|
|
101
|
+
request Channel. Explicit legacy single-Channel mode stops the Worker and
|
|
102
|
+
the next request replaces it.
|
|
94
103
|
A queued request timeout leaves active requests and Workers untouched.
|
|
95
104
|
Connect/read/write phase timeouts still need native Worker support.
|
|
96
105
|
|
|
@@ -116,8 +125,9 @@ completes. Set `WPR_RUNTIME_HOME`, `WPR_RUNTIME_DIR`, and
|
|
|
116
125
|
|
|
117
126
|
Client 1.2.0 with runtime 155.0.5 supports `ipc_backend="iocp"` and
|
|
118
127
|
`max_channels_per_worker=10` with `max_workers=1`, keeping one shared
|
|
119
|
-
cookie/proxy session while issuing concurrent Necko requests.
|
|
120
|
-
|
|
128
|
+
cookie/proxy session while issuing concurrent Necko requests. Version 1.2.0
|
|
129
|
+
uses explicit opt-in; version 1.3.0 selects these features by default.
|
|
130
|
+
Older runtimes lack these capabilities;
|
|
121
131
|
upgrade both the client and runtime before enabling multi-Channel requests.
|
|
122
132
|
See [selection, protocol, and reproducible build instructions](../source/gecko-net-worker/experiments/multiplex-network/README.md).
|
|
123
133
|
|
|
@@ -140,7 +150,8 @@ exact instantaneous maxima, or a claim of equivalent physical RAM consumption.
|
|
|
140
150
|
See [results, limitations, and reproduction commands](tests/results/http-resource-comparison-20261011.md).
|
|
141
151
|
The test entry points are `tests/integration/baidu_live_ab.py` and
|
|
142
152
|
`tests/integration/baidu_resource_ab.py`. They remain development tests; the
|
|
143
|
-
|
|
153
|
+
measurements refer to the released 1.2.0 configuration, not a claim that
|
|
154
|
+
the 1.3.0 defaults have identical resource costs.
|
|
144
155
|
|
|
145
156
|
## Network IPC diagnostics and pipe A/B
|
|
146
157
|
|
|
@@ -211,7 +222,7 @@ $env:WPR_PIPE_MODE = 'persistent'
|
|
|
211
222
|
```
|
|
212
223
|
|
|
213
224
|
```python
|
|
214
|
-
async with AsyncWprHttpClient(
|
|
225
|
+
async with AsyncWprHttpClient() as client:
|
|
215
226
|
response = await client.get("http://127.0.0.1:8080/")
|
|
216
227
|
body = await response.aread()
|
|
217
228
|
await client.flush_releases() # Optional explicit Worker-side confirmation.
|
|
@@ -225,7 +236,8 @@ pipe occupancy can delay it. Thresholds of 32 entries or 8 MiB trigger drains;
|
|
|
225
236
|
they are not global caps on unread response memory. Only acknowledged entries
|
|
226
237
|
are removed from the pending queue. Abort stops the Worker and discards its queue.
|
|
227
238
|
|
|
228
|
-
The default
|
|
239
|
+
The 1.3.0 default is `release_mode="piggyback"`; pass `"immediate"`
|
|
240
|
+
explicitly to release each response through a separate RPC. Old Workers are rejected during
|
|
229
241
|
capability negotiation if piggyback mode is requested, before any HTTP request
|
|
230
242
|
is sent. `transport_stats` covers the currently resident pool, not retired Workers.
|
|
231
243
|
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/installer.py
RENAMED
|
@@ -55,7 +55,7 @@ def _github_asset_request(release: dict[str, str]) -> urllib.request.Request:
|
|
|
55
55
|
if not token:
|
|
56
56
|
return urllib.request.Request(
|
|
57
57
|
release["url"],
|
|
58
|
-
headers={"User-Agent": "gecko-web-runtime-client/1.
|
|
58
|
+
headers={"User-Agent": "gecko-web-runtime-client/1.3.0"},
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
api = (
|
|
@@ -67,7 +67,7 @@ def _github_asset_request(release: dict[str, str]) -> urllib.request.Request:
|
|
|
67
67
|
headers={
|
|
68
68
|
"Accept": "application/vnd.github+json",
|
|
69
69
|
"Authorization": f"Bearer {token}",
|
|
70
|
-
"User-Agent": "gecko-web-runtime-client/1.
|
|
70
|
+
"User-Agent": "gecko-web-runtime-client/1.3.0",
|
|
71
71
|
"X-GitHub-Api-Version": "2022-11-28",
|
|
72
72
|
},
|
|
73
73
|
)
|
|
@@ -85,7 +85,7 @@ def _github_asset_request(release: dict[str, str]) -> urllib.request.Request:
|
|
|
85
85
|
headers={
|
|
86
86
|
"Accept": "application/octet-stream",
|
|
87
87
|
"Authorization": f"Bearer {token}",
|
|
88
|
-
"User-Agent": "gecko-web-runtime-client/1.
|
|
88
|
+
"User-Agent": "gecko-web-runtime-client/1.3.0",
|
|
89
89
|
"X-GitHub-Api-Version": "2022-11-28",
|
|
90
90
|
},
|
|
91
91
|
)
|
|
@@ -60,8 +60,8 @@ def _merge_headers(*groups: Mapping[str, str] | None) -> dict[str, str]:
|
|
|
60
60
|
class AsyncWprHttpClient:
|
|
61
61
|
"""Async HTTP client backed by a bounded pool of Gecko Network Workers.
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
the bound
|
|
63
|
+
Defaults use one Gecko cookie/profile session and up to twenty Channels.
|
|
64
|
+
Increasing the Worker bound adds independent concurrent Worker sessions;
|
|
65
65
|
each slot has its own Gecko CookieService/profile state.
|
|
66
66
|
"""
|
|
67
67
|
|
|
@@ -75,9 +75,9 @@ class AsyncWprHttpClient:
|
|
|
75
75
|
timeout: float | Timeout | None = 30.0,
|
|
76
76
|
follow_redirects: bool = True,
|
|
77
77
|
max_workers: int = 1,
|
|
78
|
-
release_mode: str = "
|
|
79
|
-
ipc_backend: str = "
|
|
80
|
-
max_channels_per_worker: int =
|
|
78
|
+
release_mode: str = "piggyback",
|
|
79
|
+
ipc_backend: str = "iocp",
|
|
80
|
+
max_channels_per_worker: int = 20,
|
|
81
81
|
) -> None:
|
|
82
82
|
try:
|
|
83
83
|
worker_limit = integer_index(max_workers)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gecko-web-runtime-client
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Thin Python client for the Firefox-derived WPR Gecko Worker protocol
|
|
5
5
|
Author: WPR project
|
|
6
6
|
License: MPL-2.0-compatible client; see the runtime bundle notices
|
|
@@ -11,6 +11,12 @@ Requires-Dist: loguru>=0.7.2; extra == "diagnostics"
|
|
|
11
11
|
|
|
12
12
|
# Python client
|
|
13
13
|
|
|
14
|
+
Version `1.3.0` defaults to one Worker, 20 Channels,
|
|
15
|
+
`ipc_backend="iocp"` and `release_mode="piggyback"`. Published version 1.2.0
|
|
16
|
+
still defaults to one Channel, threaded IPC and immediate release. Runtime
|
|
17
|
+
155.0.5 is required for the new defaults. Existing 1.2.0 installations keep
|
|
18
|
+
their behavior until explicitly upgraded.
|
|
19
|
+
|
|
14
20
|
The client provides a standard-library core plus an optional Loguru-backed
|
|
15
21
|
diagnostics layer. From this directory:
|
|
16
22
|
|
|
@@ -66,16 +72,17 @@ helpers), `network/transport.py` (the versioned Worker boundary),
|
|
|
66
72
|
|
|
67
73
|
`timeout` accepts seconds, `Timeout(total=seconds, pool=seconds)`, or `None`.
|
|
68
74
|
`total` covers queueing plus the active request; `pool` can bound waiting for
|
|
69
|
-
an available
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
an available request slot. The 1.3.0 default is one Worker with 20
|
|
76
|
+
concurrent Channels. `asyncio.gather()` submits the work; the client limits
|
|
77
|
+
active requests to `max_workers * max_channels_per_worker`. No arguments are
|
|
78
|
+
needed to discover the installed runtime and enable the default transport:
|
|
72
79
|
|
|
73
80
|
```python
|
|
74
81
|
import asyncio
|
|
75
82
|
from gecko_web_runtime import AsyncWprHttpClient
|
|
76
83
|
|
|
77
84
|
async def main():
|
|
78
|
-
async with AsyncWprHttpClient(
|
|
85
|
+
async with AsyncWprHttpClient() as client:
|
|
79
86
|
responses = await asyncio.gather(
|
|
80
87
|
*(client.get(f"https://example.com/api/{i}") for i in range(8))
|
|
81
88
|
)
|
|
@@ -87,8 +94,8 @@ async def main():
|
|
|
87
94
|
asyncio.run(main())
|
|
88
95
|
```
|
|
89
96
|
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
Channels bound in-flight requests, not HTTP sockets or Python threads. Set
|
|
98
|
+
`max_channels_per_worker` to change the single-Worker limit. Each extra
|
|
92
99
|
Worker is a separate Firefox process/profile and therefore has its own Gecko
|
|
93
100
|
CookieService state; multi-Worker cookie continuity is not shared or ordered.
|
|
94
101
|
Keep the default `max_workers=1` when requests depend on a single browser cookie
|
|
@@ -96,12 +103,14 @@ jar or when minimizing memory is more important than parallel throughput. The
|
|
|
96
103
|
pool grows lazily up to the configured cap and reuses Workers after requests.
|
|
97
104
|
For latency-sensitive bursts, call `await client.warmup(url)` immediately after
|
|
98
105
|
entering the client and before sending application requests. It starts the
|
|
99
|
-
remaining Workers and makes one full GET per
|
|
106
|
+
remaining Workers and makes one full GET per Channel slot to the supplied URL; the
|
|
100
107
|
responses are read and released while the Worker connections stay open. This
|
|
101
108
|
is real traffic, so use a safe, idempotent endpoint. Cookies set by that
|
|
102
|
-
endpoint remain isolated in each Worker profile.
|
|
103
|
-
|
|
104
|
-
|
|
109
|
+
endpoint remain isolated in each Worker profile. With the new defaults a
|
|
110
|
+
warmup call makes 20 real GETs; entering a client by itself makes none.
|
|
111
|
+
Active timeout/cancellation in the default multiplexed mode cancels only its
|
|
112
|
+
request Channel. Explicit legacy single-Channel mode stops the Worker and
|
|
113
|
+
the next request replaces it.
|
|
105
114
|
A queued request timeout leaves active requests and Workers untouched.
|
|
106
115
|
Connect/read/write phase timeouts still need native Worker support.
|
|
107
116
|
|
|
@@ -127,8 +136,9 @@ completes. Set `WPR_RUNTIME_HOME`, `WPR_RUNTIME_DIR`, and
|
|
|
127
136
|
|
|
128
137
|
Client 1.2.0 with runtime 155.0.5 supports `ipc_backend="iocp"` and
|
|
129
138
|
`max_channels_per_worker=10` with `max_workers=1`, keeping one shared
|
|
130
|
-
cookie/proxy session while issuing concurrent Necko requests.
|
|
131
|
-
|
|
139
|
+
cookie/proxy session while issuing concurrent Necko requests. Version 1.2.0
|
|
140
|
+
uses explicit opt-in; version 1.3.0 selects these features by default.
|
|
141
|
+
Older runtimes lack these capabilities;
|
|
132
142
|
upgrade both the client and runtime before enabling multi-Channel requests.
|
|
133
143
|
See [selection, protocol, and reproducible build instructions](../source/gecko-net-worker/experiments/multiplex-network/README.md).
|
|
134
144
|
|
|
@@ -151,7 +161,8 @@ exact instantaneous maxima, or a claim of equivalent physical RAM consumption.
|
|
|
151
161
|
See [results, limitations, and reproduction commands](tests/results/http-resource-comparison-20261011.md).
|
|
152
162
|
The test entry points are `tests/integration/baidu_live_ab.py` and
|
|
153
163
|
`tests/integration/baidu_resource_ab.py`. They remain development tests; the
|
|
154
|
-
|
|
164
|
+
measurements refer to the released 1.2.0 configuration, not a claim that
|
|
165
|
+
the 1.3.0 defaults have identical resource costs.
|
|
155
166
|
|
|
156
167
|
## Network IPC diagnostics and pipe A/B
|
|
157
168
|
|
|
@@ -222,7 +233,7 @@ $env:WPR_PIPE_MODE = 'persistent'
|
|
|
222
233
|
```
|
|
223
234
|
|
|
224
235
|
```python
|
|
225
|
-
async with AsyncWprHttpClient(
|
|
236
|
+
async with AsyncWprHttpClient() as client:
|
|
226
237
|
response = await client.get("http://127.0.0.1:8080/")
|
|
227
238
|
body = await response.aread()
|
|
228
239
|
await client.flush_releases() # Optional explicit Worker-side confirmation.
|
|
@@ -236,7 +247,8 @@ pipe occupancy can delay it. Thresholds of 32 entries or 8 MiB trigger drains;
|
|
|
236
247
|
they are not global caps on unread response memory. Only acknowledged entries
|
|
237
248
|
are removed from the pending queue. Abort stops the Worker and discards its queue.
|
|
238
249
|
|
|
239
|
-
The default
|
|
250
|
+
The 1.3.0 default is `release_mode="piggyback"`; pass `"immediate"`
|
|
251
|
+
explicitly to release each response through a separate RPC. Old Workers are rejected during
|
|
240
252
|
capability negotiation if piggyback mode is requested, before any HTTP request
|
|
241
253
|
is sent. `transport_stats` covers the currently resident pool, not retired Workers.
|
|
242
254
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gecko-web-runtime-client"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.3.0"
|
|
8
8
|
description = "Thin Python client for the Firefox-derived WPR Gecko Worker protocol"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/__init__.py
RENAMED
|
File without changes
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/__main__.py
RENAMED
|
File without changes
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/_leases.py
RENAMED
|
File without changes
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/api/__init__.py
RENAMED
|
File without changes
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/api/context.py
RENAMED
|
File without changes
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/api/page.py
RENAMED
|
File without changes
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/api/pool.py
RENAMED
|
File without changes
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/api/runtime.py
RENAMED
|
File without changes
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/data_plane.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/iocp_pipe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/network/_urls.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gecko_web_runtime_client-1.2.0 → gecko_web_runtime_client-1.3.0}/gecko_web_runtime/session.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|