Skip to content

Conversation

@tmc
Copy link

@tmc tmc commented Jun 10, 2025

Add WebAssembly (WASM) Support to bbolt

This PR adds comprehensive support for WebAssembly targets (js and wasip1) to bolt, enabling the database to run in browsers and WASI-compliant runtimes.

What's Changed

  • Memory-mapped I/O emulation: Since WASM doesn't support real mmap, we implement a buffer-based approach that reads the database file into memory
  • Transaction synchronization: Added a txIniter interface to handle platform-specific transaction initialization, ensuring data consistency in WASM environments where memory buffers
    need manual refresh
  • Platform-specific implementations: Created bolt_wasm.go with WASM-specific implementations of mmap, munmap, madvise, and file locking operations

Testing Infrastructure

  • Added WASM test targets in the Makefile:
    • make test-wasm for browser-based JavaScript WASM (GOOS=js)
    • make test-wasip1 for WASI Preview 1 runtime testing
  • Added GitHub Actions workflows for automated WASM testing in CI

Test Adaptations

  • Skip memory-intensive tests on WASM platforms due to runtime constraints
  • Added appropriate test guards for WASM-specific limitations

Testing

All tests pass on WASM platforms:

  • Browser WASM (GOOS=js GOARCH=wasm)
  • WASI Preview 1 (GOOS=wasip1 GOARCH=wasm)

The implementation has been tested with both wazero and wasmtime runtimes.

@k8s-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: tmc
Once this PR has been reviewed and has the lgtm label, please assign ahrtr for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot
Copy link

Hi @tmc. Thanks for your PR.

I'm waiting for a etcd-io member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@tmc tmc changed the title bolt: Add wasm support wasm: Add wasm support Jun 10, 2025
@ahrtr
Copy link
Member

ahrtr commented Jun 12, 2025

cc @Elbehery @fuweid @ivanvc @jmhbnz @tjungblu

@ivanvc
Copy link
Member

ivanvc commented Jun 12, 2025

/ok-to-test


// Allow WASM-specific transaction initialization
if runtime.GOARCH == "wasm" {
if initer, ok := any(db).(txIniter); ok {
Copy link
Member

@Elbehery Elbehery Jun 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @tmc for your prompt follow up 🚀 👍🏽

Suggested change
if initer, ok := any(db).(txIniter); ok {
if initer, ok := db.(txIniter); ok {

wdyt about this ?

Any reason to wrap db within any ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping @tmc

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type assertions must take an interface value and db is *DB which means it can't be used in a type assertion.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivanvc
Copy link
Member

ivanvc commented Jun 13, 2025

I suggest holding this pull request until we make #986 work and find a solution to cross-compile in other architectures, so we're able to catch issues in new ones early/automated, rather than waiting for someone to find out compile/build issues.

@Elbehery
Copy link
Member

Elbehery commented Jun 14, 2025

I suggest holding this pull request until we make #986 work and find a solution to cross-compile in other architectures, so we're able to catch issues in new ones early/automated, rather than waiting for someone to find out compile/build issues.

cc @ahrtr @fuweid

@ivanvc
Copy link
Member

ivanvc commented Jul 18, 2025

Now we have merged #986, which lints the files in different architectures. Would it be possible to run the linter against the js GOOS? I have no experience with this, so I'm unsure. @tmc, would you be able to add running the linter for this OS/ARCH?

@github-actions github-actions bot added the stale label Oct 17, 2025
tmc added 3 commits October 21, 2025 00:46
Add support for running bbolt in WebAssembly environments (js/wasm and wasip1):
- Implement memory management for WASM platforms without mmap
- Add platform-specific transaction initialization
- Configure smaller page size and memory limits for WASM
- Add GitHub workflow for WASM testing (js and wasip1)
- Adjust tests to handle WASM memory constraints
- Support both browser (js) and WASI environments

Signed-off-by: Travis Cline <[email protected]>
Replace os.Getpagesize() calls with common.DefaultPageSize constant and remove redundant pagesize.go implementation. Simplify WASM-specific code by removing custom initialization and page size handling. Update tests to use the new constant.

Signed-off-by: Travis Cline <[email protected]>
Update the db_test.go file to accommodate the recent WASM-related changes, including simplifying platform-specific page size handling and adjusting tests to handle WASM memory constraints.

Signed-off-by: Travis Cline <[email protected]>
@ahrtr ahrtr removed the stale label Oct 21, 2025
@Elbehery
Copy link
Member

Thanks @tmc for your contribution 🙏🏽

Copy link
Member

@Elbehery Elbehery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

the implementation of bolt_wasm.go is straight forward.

But I am in favor of using defer for releasing the lock

cc @ahrtr @ivanvc

if runtime.GOARCH == "wasm" {
if initer, ok := any(db).(txIniter); ok {
if err := initer.txInit(); err != nil {
db.metalock.Unlock()
Copy link
Member

@Elbehery Elbehery Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to precede this call with defer ?

ideally it should be move above, after acquiring the lock

if runtime.GOARCH == "wasm" {
if initer, ok := any(db).(txIniter); ok {
if err := initer.txInit(); err != nil {
db.rwlock.Unlock()
Copy link
Member

@Elbehery Elbehery Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@ahrtr
Copy link
Member

ahrtr commented Oct 21, 2025

Do not get time to dig into the details, but my immediately feeling is that this PR isn't well integrated into the existing implementations,

Pls do not get me wrong, I am supportive to add wasm support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

5 participants