Skip to content

Conversation

@sisou
Copy link
Member

@sisou sisou commented Apr 1, 2023

What's in this pull request?

Various changes, but all relatively minor, with minimal effect on the public API.

Note
This PR is best reviewed commit-by-commit, as the complete change-set might be overwhelming. I made every logical change into its own commit, with expansive descriptions in the commit messages.

If anything is unclear, please ask!

This fixes UI freezing in browsers while the client is using lots of CPU.

Pull request checklist

  • All tests pass. The project builds and runs.
  • I have resolved any merge conflicts.
  • I have resolved all clippy and rustfmt warnings.

@sisou sisou added the WASM label Apr 1, 2023
@sisou sisou requested review from jsdanielh and viquezclaudio April 1, 2023 00:18
@sisou sisou self-assigned this Apr 1, 2023
@sisou sisou force-pushed the soeren/wasm-worker branch from f0ae4d2 to 03fa52f Compare April 1, 2023 12:59
@codecov
Copy link

codecov bot commented Apr 1, 2023

Codecov Report

Patch coverage has no change and project coverage change: +0.10 🎉

Comparison is base (349d52f) 64.89% compared to head (9534d16) 64.99%.

❗ Current head 9534d16 differs from pull request most recent head ce263a0. Consider uploading reports for the commit ce263a0 to get more accurate results

Additional details and impacted files
@@              Coverage Diff              @@
##           albatross    #1534      +/-   ##
=============================================
+ Coverage      64.89%   64.99%   +0.10%     
=============================================
  Files            429      431       +2     
  Lines          54490    54498       +8     
=============================================
+ Hits           35359    35422      +63     
+ Misses         19131    19076      -55     
Flag Coverage Δ
unittests 64.99% <0.00%> (+0.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
web-client/src/address.rs 0.00% <0.00%> (ø)
web-client/src/client.rs 0.00% <0.00%> (ø)
web-client/src/client_configuration.rs 0.00% <0.00%> (ø)
web-client/src/lib.rs 100.00% <ø> (+99.88%) ⬆️
web-client/src/peer_info.rs 0.00% <0.00%> (ø)
web-client/src/transaction.rs 0.00% <0.00%> (ø)
web-client/src/transaction_builder.rs 0.00% <0.00%> (ø)

... and 11 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@jsdanielh jsdanielh added this to the Nimiq PoS Mainnet milestone Apr 20, 2023
@sisou sisou force-pushed the soeren/wasm-worker branch 3 times, most recently from 3837cee to ba92889 Compare April 24, 2023 14:05
@sisou sisou force-pushed the soeren/wasm-worker branch 2 times, most recently from 232e5e7 to 67d08d4 Compare April 26, 2023 06:29
@sisou sisou force-pushed the soeren/wasm-worker branch from 51211a5 to 9534d16 Compare May 2, 2023 09:15
sisou added 15 commits May 2, 2023 09:45
In Transaction, the method could not parse strings, because trying to cast the input into a PlainTransaction already returned early with an Err, preventing string parsing to run at all.
- The wasm-timer crate was incompatible, as it required access to window. I patched it and set the updated version to be used globally, as the libp2p-websocket-transport package, which is an indirect dependency, is also using it.
- Use wasm_timer::Delay for timeouts, instead of a custom implementation with js_sys promise and window.setTimeout.
- Chromium-based browsers do not emit offline/online events in workers, so I changed them to listen for postMessage messages from the main thread instead. The sender of those events will be in the main-thread index.js file in a later commit.
JS objects returned by wasm-bindgen'd structs are just pointers into WASM memory ({ptr: number}) with mocked class methods and properties. Since calls into in the same thread WASM are sync, users of these objects don't notice a difference.

However, proxying these structs (which **only live** in WASM memory) over to the main thread from the webworker makes all accesses async, even direct property access. That means getting e.g. `peerInfo.address` returns a `Promise<string>` instead of a `string`. Unfortunately, there is no way to represent this behavior in Typescript files, meaning users get no indication of it.

Passing plain values to JS instead copies the primitives over into JS memory, and then over to the main thread, where they are cloned and can be accessed like normal. If the struct has no methods anyway, it thus makes sense to just return a plain JS object.

For the other direction, the issue is that the object the user wants to pass from the main thread into the client in the webworker only exists in the main thread WASM memory. The client WASM in the webworker has no knowledge of it and cannot access it, especially not over the async worker barrier. This means data has to be serialized and copied over into the worker instead, which we here just simply make explicit, instead of implicit with unknown failure cases.
Similar to the last commit, we need to serialize the config to pass it from the main thread to the worker, which mean introducing a plain config version into which the config gets encoded in the main thread and decoded from in the worker.

Furthermore, this change has the advantage that `Client.create()` now simply takes a plain object with all properties optional, making it possible to pass a config object with the right properties in directly, without _having_ to go through the ClientConfiguration builder.
We cannot use TransactionBuilder client-connected, as the client and the TransactionBuilder (or at least the transactions that it outputs) live in different thread WASM memories, and accessing them from each other between these contexts is not (easily) possible.

Unfortunately, this means for now users have to specify the validity start height and network ID manually, for which I added accessor methods on the client.
Even if they aren't internally. This is because the communication from main thread to webworker can only be async. Typing it async in rust generates the correct types in Typescript.
…t APIs

For the NPM package, we create two builds, one for bundlers (that can use import from package names), and one for plain web use, that needs to specify the exact file that is imported, both in the main thread and in the webworker.

This also updates the demo (now in example/) module.js file to use the updated client API, using the TransactionBuilder statically and passing serialized (to hex in this case) transactions when sending them. No other changes are required in the demo file.

The `Client` class/object defined in dist/client-proxy.js _shadows_ the `class Client` exported by the worker types and adheres to that one's static API. For the user it is transparent.
In preparation for the introduction of features in the next commit.
This way the primitives-only (offline) build is much smaller (unoptimized 7.0MB -> 810kB)
…d targets

Making both feature builds smaller.
jsdanielh and others added 4 commits May 2, 2023 09:46
Fix the setting of the log level for the client. The `primitives`
feature was missing the `camelCase` `serde` directive and the `Tsify`
derive directive for the `ClientConfiguration` struct.
Also made the `primitives` and `client` features the default features
and changed the script to disable the default features.
Also changes the script to use `set -e` to avoid the usage of `&&` in
each line.
Add handler to trigger the check of peers on the `visible` event from
the `visibilitychange` event list from the document.
By transparently serializing them to their plain format before being sent to the worker.
@jsdanielh
Copy link
Member

Rebasing it to get it merged

@jsdanielh jsdanielh force-pushed the soeren/wasm-worker branch from 9534d16 to ce263a0 Compare May 2, 2023 15:47
@jsdanielh jsdanielh merged commit ce263a0 into albatross May 2, 2023
@jsdanielh jsdanielh deleted the soeren/wasm-worker branch May 2, 2023 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants