Make internal-dev less debug specific

- Evergreen the drip test
- Add setup config to MixFetch instance
This commit is contained in:
mfahampshire
2026-04-01 10:34:47 +01:00
parent 114e9b2f15
commit e656157284
5 changed files with 300 additions and 274 deletions
+31 -11
View File
@@ -20,6 +20,27 @@
<label><input type="radio" name="gateway-mode" value="random" />
Random Gateway</label>
</div>
<details style="margin-top: 8px">
<summary style="cursor: pointer; font-size: 0.9em; color: #555">Advanced Options</summary>
<div style="margin-top: 6px; padding: 8px; background: #f9f9f9; font-size: 0.9em">
<div>
<label><input type="checkbox" id="opt-force-tls" checked /> Force TLS</label>
</div>
<div style="margin-top: 4px">
<label>Client ID: <input type="text" id="opt-client-id" value="my-client" size="20" /></label>
</div>
<div style="margin-top: 4px">
<label><input type="checkbox" id="opt-disable-poisson" checked /> Disable Poisson packet distribution</label>
</div>
<div style="margin-top: 4px">
<label><input type="checkbox" id="opt-disable-cover" checked /> Disable cover traffic</label>
</div>
<div style="margin-top: 4px">
<label>Request timeout (ms): <input type="number" id="opt-request-timeout" value="60000" min="1000" max="300000" style="width: 80px" /></label>
</div>
</div>
</details>
<div style="margin-top: 8px">
<button id="start-mixfetch">Start MixFetch</button>
<span id="mixfetch-status" style="margin-left: 10px; color: gray">Not started</span>
@@ -79,30 +100,29 @@
<div id="stress-drip-opts" style="display: none; margin-top: 8px; padding: 8px; background: #f9f9f9">
<p style="margin: 0 0 4px; font-size: 0.85em; color: #666">
Uses <code>httpbin.org/drip</code> to slowly drip bytes over a set duration,
keeping connections alive for a controlled time. Profiles are designed to
straddle the Go timeout boundary &mdash; some will finish just in time,
others will be mid-transfer when the timeout fires. This is how we
reproduce the Go runtime panic (see DEBUGGING_NOTES.md).
keeping connections alive for a controlled time. Profiles are computed from
the Go timeout value below, so they always straddle the configured boundary
&mdash; some finish well before the timeout, others are mid-transfer when it fires.
</p>
<table style="font-size: 0.9em; border-collapse: collapse">
<tr>
<td style="padding: 1px 10px 1px 0"><b>safe</b></td>
<td>30s</td>
<td style="padding-left: 10px; color: #666">well under 60s timeout</td>
<td>~50% of timeout</td>
<td style="padding-left: 10px; color: #666">well under the limit</td>
</tr>
<tr>
<td style="padding: 1px 10px 1px 0"><b>boundary</b></td>
<td>55s</td>
<td style="padding-left: 10px; color: #666">55s server + ~10s mixnet latency = over</td>
<td>~92% of timeout</td>
<td style="padding-left: 10px; color: #666">server-side OK, but mixnet latency pushes it over</td>
</tr>
<tr>
<td style="padding: 1px 10px 1px 0"><b>over</b></td>
<td>65s</td>
<td style="padding-left: 10px; color: #666">exceeds 60s timeout on its own</td>
<td>~108% of timeout</td>
<td style="padding-left: 10px; color: #666">exceeds the timeout on its own</td>
</tr>
<tr>
<td style="padding: 1px 10px 1px 0"><b>slow-start</b></td>
<td>10s delay + 50s</td>
<td>~17% delay + ~83% drip</td>
<td style="padding-left: 10px; color: #666">late first byte, then long transfer</td>
</tr>
</table>
+29 -13
View File
@@ -48,8 +48,8 @@ class WebWorkerClient {
};
}
startMixFetch = (preferredGateway) => {
this.worker.postMessage({ kind: "StartMixFetch", args: { preferredGateway } });
startMixFetch = (preferredGateway, setupOpts) => {
this.worker.postMessage({ kind: "StartMixFetch", args: { preferredGateway, setupOpts } });
};
doFetch = (target) => {
@@ -82,12 +82,24 @@ async function main() {
const gatewayMode = document.querySelector('input[name="gateway-mode"]:checked').value;
const preferredGateway = gatewayMode === "default" ? DEFAULT_GATEWAY : undefined;
const setupOpts = {
forceTls: document.getElementById("opt-force-tls").checked,
clientId: document.getElementById("opt-client-id").value,
disablePoisson: document.getElementById("opt-disable-poisson").checked,
disableCover: document.getElementById("opt-disable-cover").checked,
requestTimeoutMs: parseInt(document.getElementById("opt-request-timeout").value, 10),
};
document.querySelector("#start-mixfetch").disabled = true;
document.querySelectorAll('input[name="gateway-mode"]').forEach((r) => (r.disabled = true));
updateStatus("mixfetch-status", "Starting...", "orange");
// Sync the stress-test Go timeout to match the configured request timeout
document.getElementById("stress-go-timeout").value = setupOpts.requestTimeoutMs;
console.log(`Starting MixFetch (${gatewayMode} gateway${preferredGateway ? `: ${preferredGateway}` : ""})...`);
client.startMixFetch(preferredGateway);
console.log("Setup options:", setupOpts);
client.startMixFetch(preferredGateway, setupOpts);
};
document.querySelector("#fetch-button-1").onclick = () => doFetch(1);
@@ -109,7 +121,7 @@ async function main() {
updateStatus("stress-test-status", "Running...", "orange");
client.setGoTimeout(goTimeoutMs);
const requests = generateStressRequests(count, mode);
const requests = generateStressRequests(count, mode, goTimeoutMs);
stressTest = {
count,
mode,
@@ -184,14 +196,16 @@ const STRESS_PROFILES = [
{ label: "xlarge", bytes: 1048576 },
];
const DRIP_PROFILES = [
{ label: "safe", dripDuration: 30, dripDelay: 0, dripBytes: 100 },
{ label: "boundary", dripDuration: 55, dripDelay: 0, dripBytes: 100 },
{ label: "over", dripDuration: 65, dripDelay: 0, dripBytes: 100 },
{ label: "slow-start", dripDuration: 50, dripDelay: 10, dripBytes: 100 },
];
function buildDripProfiles(timeoutSec) {
return [
{ label: "safe", dripDuration: Math.round(timeoutSec * 0.50), dripDelay: 0, dripBytes: 100 },
{ label: "boundary", dripDuration: Math.round(timeoutSec * 0.92), dripDelay: 0, dripBytes: 100 },
{ label: "over", dripDuration: Math.round(timeoutSec * 1.08), dripDelay: 0, dripBytes: 100 },
{ label: "slow-start", dripDuration: Math.round(timeoutSec * 0.83), dripDelay: Math.round(timeoutSec * 0.17), dripBytes: 100 },
];
}
function generateStressRequests(count, mode) {
function generateStressRequests(count, mode, timeoutMs) {
const requests = [];
if (mode === "uniform") {
const baseUrl = document.getElementById("stress-test-url").value;
@@ -199,8 +213,9 @@ function generateStressRequests(count, mode) {
requests.push({ id: i, url: `${baseUrl}${i}`, label: "uniform", bytes: null });
}
} else if (mode === "drip") {
const dripProfiles = buildDripProfiles(timeoutMs / 1000);
for (let i = 1; i <= count; i++) {
const p = DRIP_PROFILES[Math.floor(Math.random() * DRIP_PROFILES.length)];
const p = dripProfiles[Math.floor(Math.random() * dripProfiles.length)];
requests.push({
id: i,
url: `https://httpbin.org/drip?duration=${p.dripDuration}&numbytes=${p.dripBytes}&delay=${p.dripDelay}&code=200`,
@@ -324,7 +339,8 @@ function onStressTestFetchResult(result) {
console.log("Completion order:", stressTest.completionOrder);
// Per-profile breakdown in console
const profileList = stressTest.mode === "drip" ? DRIP_PROFILES : STRESS_PROFILES;
const profileLabels = Object.keys(trackerData);
const profileList = profileLabels.map((label) => ({ label }));
if (stressTest.mode === "mixed" || stressTest.mode === "drip") {
const table = [];
for (const profile of profileList) {
+2 -2
View File
@@ -1,11 +1,11 @@
{
"name": "create-wasm-app",
"name": "mix-fetch-internal-dev",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "create-wasm-app",
"name": "mix-fetch-internal-dev",
"version": "0.1.0",
"license": "Apache-2.0",
"dependencies": {
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "create-wasm-app",
"name": "mix-fetch-internal-dev",
"version": "0.1.0",
"description": "create an app to fetch data through the mixnet",
"description": "Internal dev/stress-test harness for mix-fetch WASM",
"main": "index.js",
"bin": {
"create-wasm-app": ".bin/create-wasm-app.js"
@@ -13,7 +13,7 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/rustwasm/create-wasm-app.git"
"url": "git+https://github.com/nymtech/nym.git"
},
"keywords": [
"webassembly",
+235 -245
View File
@@ -12,31 +12,31 @@
// See the License for the specific language governing permissions and
// limitations under the License.
const RUST_WASM_URL = "mix_fetch_wasm_bg.wasm"
const GO_WASM_URL = "go_conn.wasm"
const RUST_WASM_URL = "mix_fetch_wasm_bg.wasm";
const GO_WASM_URL = "go_conn.wasm";
importScripts('mix_fetch_wasm.js');
importScripts('wasm_exec.js');
importScripts("mix_fetch_wasm.js");
importScripts("wasm_exec.js");
console.log('Initializing worker');
console.log("Initializing worker");
// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts`
const {
default_debug,
no_cover_debug,
NymClient,
set_panic_hook,
Config,
GatewayEndpointConfig,
ClientStorage,
MixFetchConfig,
send_client_data,
start_new_mixnet_connection,
setupMixFetch,
disconnectMixFetch,
setupMixFetchWithConfig,
mix_fetch_initialised,
finish_mixnet_connection
default_debug,
no_cover_debug,
NymClient,
set_panic_hook,
Config,
GatewayEndpointConfig,
ClientStorage,
MixFetchConfig,
send_client_data,
start_new_mixnet_connection,
setupMixFetch,
disconnectMixFetch,
setupMixFetchWithConfig,
mix_fetch_initialised,
finish_mixnet_connection,
} = wasm_bindgen;
let client = null;
@@ -45,281 +45,271 @@ const go = new Go(); // Defined in wasm_exec.js
var goWasm;
let mixFetchReady = false;
function sendLog(message, level = 'info') {
self.postMessage({
kind: 'Log',
args: { message, level },
});
function sendLog(message, level = "info") {
self.postMessage({
kind: "Log",
args: { message, level },
});
}
function sendReady() {
self.postMessage({ kind: 'MixFetchReady' });
self.postMessage({ kind: "MixFetchReady" });
}
function sendError(error) {
self.postMessage({
kind: 'MixFetchError',
args: { error: String(error) },
});
self.postMessage({
kind: "MixFetchError",
args: { error: String(error) },
});
}
async function logFetchResult(res) {
console.log(res)
let text = await res.text()
console.log("HEADERS: ", ...res.headers)
console.log("STATUS: ", res.status)
console.log("STATUS TEXT: ", res.statusText)
console.log("OK: ", res.ok)
console.log("TYPE: ", res.type)
console.log("URL: ", res.url)
console.log("BODYUSED: ", res.bodyUsed)
console.log("REDIRECTED: ", res.redirected)
console.log("TEXT: ", text)
console.log(res);
let text = await res.text();
console.log("HEADERS: ", ...res.headers);
console.log("STATUS: ", res.status);
console.log("STATUS TEXT: ", res.statusText);
console.log("OK: ", res.ok);
console.log("TYPE: ", res.type);
console.log("URL: ", res.url);
console.log("BODYUSED: ", res.bodyUsed);
console.log("REDIRECTED: ", res.redirected);
console.log("TEXT: ", text);
self.postMessage({
kind: 'DisplayString',
args: {
rawString: text,
},
});
self.postMessage({
kind: "DisplayString",
args: {
rawString: text,
},
});
}
async function wasm_bindgenSetup() {
const preferredGateway = "6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM";
const validator = 'https://qa-nym-api.qa.nymte.ch/api';
/*
* ── Alternative MixFetch setup ──────────────────────────────
*
* Shows how to pass custom MixFetchConfig options: specific network requester
* address, validator URL, or debug overrides. Uncomment and adapt if you
* need non-default setup for local testing.
*
* async function wasm_bindgenSetup() {
* const preferredGateway = "6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM";
* const validator = 'https://qa-nym-api.qa.nymte.ch/api';
*
* const mixFetchNetworkRequesterAddress = "2o47bhnXWna6VEyt4mXMGQQAbXfpKmX7BkjkxUz8uQVi...";
*
* // MixFetchConfigOpts: { id?, nymApi?, nyxd?, debug? }
* const differentDebug = default_debug()
* differentDebug.traffic.use_extended_packet_size = true
* differentDebug.traffic.average_packet_delay_ms = 666
*
* const config = new MixFetchConfig(mixFetchNetworkRequesterAddress, {debug: differentDebug});
*
* // MixFetchOptsSimple: { preferredGateway?, storagePassphrase? }
* await setupMixFetchWithConfig(config)
* }
*/
// local
const mixFetchNetworkRequesterAddress = "2o47bhnXWna6VEyt4mXMGQQAbXfpKmX7BkjkxUz8uQVi.6uQGnCqSczpXwh86NdbsCoDDXuqZQM9Uwko8GE7uC9g8@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM";
// const mixFetchNetworkRequesterAddress= "GqiGWmKRCbGQFSqH88BzLKijvZgipnqhmbNFsmkZw84t.4L8sXFuAUyUYyHZYgMdM3AtiusKnYUft6Pd8e41rrCHA@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM";
async function nativeSetup(preferredGateway, setupOpts = {}) {
sendLog("Setting up MixFetch...");
if (preferredGateway) {
sendLog(`Using preferred gateway: ${preferredGateway}`);
} else {
sendLog("Using random gateway selection");
}
// STEP 1. construct config
// those are just some examples, there are obviously more permutations;
// note, the extra optional argument is of the following type:
// /*
// export interface MixFetchConfigOpts {
// id?: string;
// nymApi?: string;
// nyxd?: string;
// debug?: DebugWasm;
// }
// */
//
// const debug = no_cover_debug()
//
// #1
// const config = new MixFetchConfig(mixFetchNetworkRequesterAddress, { id: 'my-awesome-mix-fetch-client', nymApi: validator, debug: debug} );
// #2
// const config = new MixFetchConfig(mixFetchNetworkRequesterAddress, { nymApi: validator, debug: debug} );
// #3
// const config = new MixFetchConfig(mixFetchNetworkRequesterAddress, { id: 'my-awesome-mix-fetch-client' } );
//
// #4
const differentDebug = default_debug()
const updatedTraffic = differentDebug.traffic;
updatedTraffic.use_extended_packet_size = true
updatedTraffic.average_packet_delay_ms = 666;
differentDebug.traffic = updatedTraffic;
const {
forceTls = true,
clientId = "my-client",
disablePoisson = true,
disableCover = true,
requestTimeoutMs = 60000,
} = setupOpts;
const config = new MixFetchConfig(mixFetchNetworkRequesterAddress, {debug: differentDebug});
//
// // STEP 2. setup the client
// // note, the extra optional argument is of the following type:
// /*
// export interface MixFetchOptsSimple {
// preferredGateway?: string;
// storagePassphrase?: string;
// }
// */
// #1
await setupMixFetchWithConfig(config)
//
// #2
// await setupMixFetchWithConfig(config, { storagePassphrase: "foomp" })
//
// #3
// await setupMixFetchWithConfig(config, { storagePassphrase: "foomp", preferredGateway })
const noCoverTrafficOverride = {
traffic: { disableMainPoissonPacketDistribution: disablePoisson },
coverTraffic: { disableLoopCoverTrafficStream: disableCover },
};
const mixFetchOverride = {
requestTimeoutMs,
};
const opts = {
forceTls,
clientId,
clientOverride: noCoverTrafficOverride,
mixFetchOverride,
};
if (preferredGateway) {
opts.preferredGateway = preferredGateway;
}
sendLog(
`Setup config: forceTls=${forceTls}, clientId=${clientId}, disablePoisson=${disablePoisson}, disableCover=${disableCover}, timeout=${requestTimeoutMs}ms`
);
sendLog("Calling setupMixFetch...");
await setupMixFetch(opts);
sendLog("setupMixFetch completed");
}
async function nativeSetup(preferredGateway) {
sendLog('Setting up MixFetch...');
if (preferredGateway) {
sendLog(`Using preferred gateway: ${preferredGateway}`);
} else {
sendLog('Using random gateway selection');
}
async function startMixFetch(preferredGateway, setupOpts) {
sendLog("Instantiating MixFetch...");
const noCoverTrafficOverride = {
traffic: {disableMainPoissonPacketDistribution: true},
coverTraffic: {disableLoopCoverTrafficStream: true},
}
const mixFetchOverride = {
requestTimeoutMs: 60000
}
const opts = {
forceTls: true,
clientId: "my-client",
clientOverride: noCoverTrafficOverride,
mixFetchOverride,
};
if (preferredGateway) {
opts.preferredGateway = preferredGateway;
}
sendLog('Calling setupMixFetch...');
await setupMixFetch(opts);
sendLog('setupMixFetch completed');
}
async function startMixFetch(preferredGateway) {
sendLog('Instantiating MixFetch...');
try {
await nativeSetup(preferredGateway);
mixFetchReady = true;
sendLog('MixFetch client running!');
sendReady();
} catch (e) {
sendLog('Failed to start MixFetch: ' + e, 'error');
sendError(e);
}
try {
await nativeSetup(preferredGateway, setupOpts);
mixFetchReady = true;
sendLog("MixFetch client running!");
sendReady();
} catch (e) {
sendLog("Failed to start MixFetch: " + e, "error");
sendError(e);
}
}
async function handleFetchPayload(target) {
if (!mixFetchReady) {
sendLog('MixFetch not ready yet', 'error');
return;
}
if (!mixFetchReady) {
sendLog("MixFetch not ready yet", "error");
return;
}
const url = target;
const args = {mode: "unsafe-ignore-cors"};
const url = target;
const args = { mode: "unsafe-ignore-cors" };
try {
sendLog(`Fetching: ${url}`);
const mixFetchRes = await mixFetch(url, args);
sendLog('Fetch completed');
await logFetchResult(mixFetchRes);
} catch (e) {
sendLog('Fetch request failure: ' + e, 'error');
console.error("mix fetch request failure: ", e);
}
try {
sendLog(`Fetching: ${url}`);
const mixFetchRes = await mixFetch(url, args);
sendLog("Fetch completed");
await logFetchResult(mixFetchRes);
} catch (e) {
sendLog("Fetch request failure: " + e, "error");
console.error("mix fetch request failure: ", e);
}
}
async function handleStressTestFetch(id, url, label) {
if (!mixFetchReady) {
sendLog('MixFetch not ready yet', 'error');
return;
}
if (!mixFetchReady) {
sendLog("MixFetch not ready yet", "error");
return;
}
const tag = `[stress #${id} ${label}]`;
const start = performance.now();
const args = { mode: "unsafe-ignore-cors" };
const tag = `[stress #${id} ${label}]`;
const start = performance.now();
const args = { mode: "unsafe-ignore-cors" };
try {
sendLog(`${tag} Fetching: ${url}`);
const res = await mixFetch(url, args);
const text = await res.text();
const elapsed = ((performance.now() - start) / 1000).toFixed(2);
sendLog(`${tag} ${res.status} OK in ${elapsed}s (${text.length} bytes)`);
self.postMessage({
kind: 'StressTestFetchResult',
args: { id, ok: true, status: res.status, elapsed, textLength: text.length, body: text },
});
} catch (e) {
const elapsed = ((performance.now() - start) / 1000).toFixed(2);
sendLog(`${tag} FAILED in ${elapsed}s: ${e}`, 'error');
self.postMessage({
kind: 'StressTestFetchResult',
args: { id, ok: false, elapsed, error: String(e) },
});
}
try {
sendLog(`${tag} Fetching: ${url}`);
const res = await mixFetch(url, args);
const text = await res.text();
const elapsed = ((performance.now() - start) / 1000).toFixed(2);
sendLog(`${tag} ${res.status} OK in ${elapsed}s (${text.length} bytes)`);
self.postMessage({
kind: "StressTestFetchResult",
args: {
id,
ok: true,
status: res.status,
elapsed,
textLength: text.length,
body: text,
},
});
} catch (e) {
const elapsed = ((performance.now() - start) / 1000).toFixed(2);
sendLog(`${tag} FAILED in ${elapsed}s: ${e}`, "error");
self.postMessage({
kind: "StressTestFetchResult",
args: { id, ok: false, elapsed, error: String(e) },
});
}
}
function setupMessageHandler() {
self.onmessage = async event => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case 'StartMixFetch': {
const { preferredGateway } = event.data.args;
await startMixFetch(preferredGateway);
break;
}
case 'FetchPayload': {
const { target } = event.data.args;
await handleFetchPayload(target);
break;
}
case 'SetGoTimeout': {
const { timeoutMs } = event.data.args;
sendLog(`Setting Go-side request timeout to ${timeoutMs}ms`);
self.__go_rs_bridge__.goWasmSetMixFetchRequestTimeout(timeoutMs);
break;
}
case 'StressTestFetch': {
const { id, url, label } = event.data.args;
// NOT awaited — each request runs independently,
// just like separate callers in a real app
handleStressTestFetch(id, url, label);
break;
}
}
self.onmessage = async (event) => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case "StartMixFetch": {
const { preferredGateway, setupOpts } = event.data.args;
await startMixFetch(preferredGateway, setupOpts);
break;
}
};
case "FetchPayload": {
const { target } = event.data.args;
await handleFetchPayload(target);
break;
}
case "SetGoTimeout": {
const { timeoutMs } = event.data.args;
sendLog(`Setting Go-side request timeout to ${timeoutMs}ms`);
self.__go_rs_bridge__.goWasmSetMixFetchRequestTimeout(timeoutMs);
break;
}
case "StressTestFetch": {
const { id, url, label } = event.data.args;
// NOT awaited — each request runs independently,
// just like separate callers in a real app
handleStressTestFetch(id, url, label);
break;
}
}
}
};
}
// TODO: look into https://www.aaron-powell.com/posts/2019-02-08-golang-wasm-5-compiling-with-webpack/
async function loadGoWasm() {
const resp = await fetch(GO_WASM_URL);
const resp = await fetch(GO_WASM_URL);
if ('instantiateStreaming' in WebAssembly) {
const wasmObj = await WebAssembly.instantiateStreaming(resp, go.importObject)
goWasm = wasmObj.instance
go.run(goWasm)
} else {
const bytes = await resp.arrayBuffer()
const wasmObj = await WebAssembly.instantiate(bytes, go.importObject)
goWasm = wasmObj.instance
go.run(goWasm)
}
if ("instantiateStreaming" in WebAssembly) {
const wasmObj = await WebAssembly.instantiateStreaming(
resp,
go.importObject
);
goWasm = wasmObj.instance;
go.run(goWasm);
} else {
const bytes = await resp.arrayBuffer();
const wasmObj = await WebAssembly.instantiate(bytes, go.importObject);
goWasm = wasmObj.instance;
go.run(goWasm);
}
}
function setupRsGoBridge() {
// (note: reason for intermediate `__rs_go_bridge__` object is to decrease global scope bloat
// and to discourage users from trying to call those methods directly)
self.__rs_go_bridge__ = {}
self.__rs_go_bridge__.send_client_data = send_client_data
self.__rs_go_bridge__.start_new_mixnet_connection = start_new_mixnet_connection
self.__rs_go_bridge__.mix_fetch_initialised = mix_fetch_initialised
self.__rs_go_bridge__.finish_mixnet_connection = finish_mixnet_connection
// (note: reason for intermediate `__rs_go_bridge__` object is to decrease global scope bloat
// and to discourage users from trying to call those methods directly)
self.__rs_go_bridge__ = {};
self.__rs_go_bridge__.send_client_data = send_client_data;
self.__rs_go_bridge__.start_new_mixnet_connection =
start_new_mixnet_connection;
self.__rs_go_bridge__.mix_fetch_initialised = mix_fetch_initialised;
self.__rs_go_bridge__.finish_mixnet_connection = finish_mixnet_connection;
}
async function main() {
sendLog('Worker starting...');
sendLog("Worker starting...");
// load rust WASM package
sendLog('Loading Rust WASM...');
await wasm_bindgen(RUST_WASM_URL);
sendLog('Loaded Rust WASM');
// load rust WASM package
sendLog("Loading Rust WASM...");
await wasm_bindgen(RUST_WASM_URL);
sendLog("Loaded Rust WASM");
// load go WASM package
sendLog('Loading Go WASM...');
await loadGoWasm();
sendLog('Loaded Go WASM');
// load go WASM package
sendLog("Loading Go WASM...");
await loadGoWasm();
sendLog("Loaded Go WASM");
// sets up better stack traces in case of in-rust panics
set_panic_hook();
// sets up better stack traces in case of in-rust panics
set_panic_hook();
setupRsGoBridge();
setupRsGoBridge();
goWasmSetLogging("trace")
goWasmSetLogging("trace");
// Set up message handler (MixFetch will be started on demand)
setupMessageHandler();
// Set up message handler (MixFetch will be started on demand)
setupMessageHandler();
sendLog('Worker ready - click Start MixFetch to begin');
sendLog("Worker ready - click Start MixFetch to begin");
}
// Let's get started!
main();
main();