Skip to content

Commit

Permalink
feat: add the documentation site to the project (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
Angelmmiguel committed Oct 17, 2022
1 parent 03981bf commit c5293a7
Show file tree
Hide file tree
Showing 23 changed files with 22,116 additions and 0 deletions.
20 changes: 20 additions & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Dependencies
/node_modules

# Production
/build

# Generated files
.docusaurus
.cache-loader

# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
23 changes: 23 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Documentation

The Wasm Workers Server documentation is developed with [Docusaurus](https://docusaurus.io/).

## Edit the documentation

### Prerequisites

You will need:

- [NodeJS](https://nodejs.org/)

### Development

To start the documentation development server, run these commands:

```sh
cd docs && \
npm install && \
npm start
```

Then, you can access the documentation site at <http://localhost:3000>.
3 changes: 3 additions & 0 deletions docs/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};
8 changes: 8 additions & 0 deletions docs/docs/features/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "Features",
"position": 4,
"link": {
"type": "generated-index"
}
}

24 changes: 24 additions & 0 deletions docs/docs/features/key-value.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
sidebar_position: 2
---

# Key / Value Store

Wasm Workers Server integrates an in-memory [Key / Value (K/V) store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database). This K/V store allows to read and write data from the different workers.

For now, the data is only stored in memory and cleaned up in every restart.

## How it works?

The K/V store follows the same approach as [Requests / Responses](../how-it-works.md#how-it-works). On every request, the worker receive a snapshot of the K/V status for the configured namespace.

The worker may access all the data and perform changes over it. Then, a new K/V status is returned and the internal status is override.

### Add a K/V to a worker

* [Add a K/V store to JavaScript workers](../tutorials/javascript-workers.md#add-a-key--value-store)
* [Add a K/V store to Rust workers](../tutorials/rust-workers.md#add-a-key--value-store)

## Limitations

A known limitation from the snapshot approach is the data override when concurrent requests are writing to the same namespace. In the future, we will implement a consolidation mechanism or a different store type for applications that require to write intensively.
43 changes: 43 additions & 0 deletions docs/docs/how-it-works.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
sidebar_position: 3
---

# How it works?

Wasm Workers is built around two main ideas:

* **Handlers receive requests and return responses**.

We follow this approach as it's a widely used pattern for creating serverless functions. Following this pattern helps us to keep compatibility with multiple platforms and avoid vendor-locking on our own tool.

* **Handlers receive and return data via WASI Stdio**.

To increase compatibility and simplify the integration with existing languages, we decided to send and receive data using `STDIN` / `STDOUT`. So, any language that can be compiled using WASI standard can create compatible handlers with Wasm Workers.

## Runner

Based on these two principles, the server performs the following tasks:

* Identify `.wasm` modules in the given folder
* Associate a HTTP route to every module
* Create a Key / Value in-memory store if required
* Initialize the [Wasmtime](https://wasmtime.dev/) runtime
* Compile the different modules and initialize them
* Spin a HTTP server to start serving the requests

## Convention over configuration

Wasm Workers assume the HTTP routes from the filesystem. This approach is pretty similar to other very successful projects like NextJS. This simplifies the server interface by running without adding any configuring file.

For extra features such as the Key / Value store, you need to write a configuration file. By default, Wasm Workers doesn't enable any extra feature to any worker. This is an example configuration file to enable the Key / Value store for a handler:

```toml title="./counter.toml"
name = "counter"
version = "1"

[data]
[data.kv]
namespace = "counter"
```

These files are only required to enable extra features for your handlers.
53 changes: 53 additions & 0 deletions docs/docs/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
sidebar_position: 1
---

# What's Wasm Workers Server?

Wasm Workers Server is a project that allows you to run serverless code using a lightweight construct called ‘workers’, explained later in the document. Ther server itself is implemented as a self-contained binary that routes HTTP requests to a WebAssembly runtime that hosts the workers. It looks for .wasm and other compatible modules (like JavaScript files) in the given folder and associate HTTP endpoints based on their path:

```bash
$ wws --help
Usage: wws [OPTIONS] [PATH]

Arguments:
[PATH] Folder to read WebAssembly modules from [default: .]

Options:
--host <HOSTNAME> Hostname to initiate the server [default: 127.0.0.1]
-p, --port <PORT> Port to initiate the server [default: 8080]
-h, --help Print help information
-V, --version Print version information
```

You don't need to configure anything by default. Just drop your workers in a folder and run the project to get an HTTP server and start serving requests 🚀.

```bash
$ curl http://localhost:8080/api/hello

Hello Wasm!
```

That's all! Now it's your turn [to download and start using Wasm Workers Server](./start.md).

# What's a worker?

Worker has many definitions in the software ecosystem. In the context of the Web Platform, **a worker is a resource that listens to events and replies to them**. In our context, **a worker is a script or function that receives an HTTP request and returns an HTTP response**.

Applications can be developed by combining multiple workers. Every worker listens to certain events and provides responses to them. Splitting large applications into smaller pieces has several benefits:

* **Easier to develop**: workers are meant to be small and focused.
* **Easier to test**: every worker can be tested separately and the surface to cover with testing is way smaller.
* **Easier to deploy**: new platforms are focusing on workers and deploying existing applications is just a single command.

This concept may sound familiar to you. [Serverless computing](https://en.wikipedia.org/wiki/Serverless_computing) is a popular model to build web applications. Services like [AWS Lambda](https://aws.amazon.com/lambda/) and [Google Cloud Functions](https://cloud.google.com/functions) implements this model.

Workers is an implementation of serverless. Many of the existing serverless platforms run functions in a centralized infrastructure where related services are close to them. With the workers model, platforms like [Cloudflare Workers®](https://workers.cloudflare.com/), [Deno Deploy](https://deno.com/deploy), [Vercel](https://vercel.com/), [Fermyon](https://www.fermyon.com/) and [Suborbital](https://suborbital.dev/) deploy your workers close to your users. For this task, they created a new set of "edge runtimes" that allows them to quickly distribute your workers around the globe.

## Why Wasm Workers Server?

Wasm Workers Server is a lightweight implementation of a Worker platform that aims for compatibility. You can use it to develop applications locally quickly or to host your applications on servers that you control entirely. It is extremely easy to get started: just download a binary and start writing your workers. You can create them based on different languages and run them securely thanks to [WebAssembly](https://webassembly.org/).

It aims for compatibility and follows an ongoing specification that different companies are working under the name of [WinterCG](https://wintercg.org/faq). This working group aims to create a common API for using Web Platform APIs like workers outside of the browser.

Many of the platforms mentioned earlier follow a similar approach, so any code you write for Wasm Workers Server can be moved to those platforms easily (or the other way around!). Remember that our focus with wws is simplicity and compatibility. Since this is a growing ecosystem, we want you to start quickly and move wherever you need.
46 changes: 46 additions & 0 deletions docs/docs/start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
sidebar_position: 2
---

# Getting Started

Wasm Workers runs almost anywhere. Thanks to its portability, downloading and running it anywhere is quite simple:

```bash
$ curl https://raw.githubusercontent.com/vmware-labs/wasm-workers-server/main/install.sh | bash
$ wws --help
Usage: wws [OPTIONS] [PATH]

Arguments:
[PATH] Folder to read WebAssembly modules from [default: .]

Options:
--host <HOSTNAME> Hostname to initiate the server [default: 127.0.0.1]
-p, --port <PORT> Port to initiate the server [default: 8080]
-h, --help Print help information
-V, --version Print version information
```

You can download some of our example `.wasm` modules and try them:

```bash
$ curl https://raw.githubusercontent.com/vmware-labs/wasm-workers-server/main/examples/compiled/hello.wasm \
-o ./index.wasm
$ wasm-workers .
⚙️ Loading routes from: ./examples
🗺 Detected routes:
- http://127.0.0.1:8080/
=> index.wasm (handler: default)
🚀 Start serving requests at http://127.0.0.1:8080
```

Now, open your browser at <http://127.0.0.1:8080>.

## Next Steps

Now you got the taste of Wasm Workers, it's time to create your first handler:

* [Create your first JavaScript handler](./tutorials/javascript-workers.md)
* [Create your first Rust handler](./tutorials/rust-workers.md)

And if you are curious, here you have a guide about [how it works](./how-it-works.md).
8 changes: 8 additions & 0 deletions docs/docs/tutorials/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "Tutorials",
"position": 5,
"link": {
"type": "generated-index",
"description": "Learn how to create new workers."
}
}
129 changes: 129 additions & 0 deletions docs/docs/tutorials/javascript-workers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
sidebar_position: 1
---

# Create a JavaScript worker

Workers based on JavaScript work out of the box with Wasm Workers Server. The server integrates a JavaScript interpreter compiled into a WebAssembly module. Currently, the interpreter we support is [quickjs](https://bellard.org/quickjs/), although we are working on adding new ones.

## Your first worker

JavaScript workers are based on the [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) / [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) objects from the Web Fetch API. Your worker needs to listen to the `fetch` event, that will include a associated `Request` object. The worker function will receive the request and generate a `Response` object to reply to the request.

In this example, the worker will get a request and print all the related information.

1. First, create a new `index.js` file with the following content. It is the minimum code you need to subscribe to the fetch event and return a valid response.

```javascript title="./index.js"
const reply = (request) => {
return new Response("Hello Wasm!");
}

// Subscribe to the Fetch event
addEventListener("fetch", event => {
return event.respondWith(reply(event.request));
});
```

1. Now, you can add more content to the `reply` function to show the request information. In addition to that, let's add a response header.

```javascript title="./index.js"
const reply = (request) => {
// Body response
const body = `<!DOCTYPE html>
<body>
<h1>Hello from Wasm Workers Server</h1>
<p>Replying to ${request.url}</p>
<p>Method: ${request.method}</p>
<p>User Agent: ${request.headers.get("userAgent")}</p>
<p>Payload: ${request.body || "-"}</p>
<p>
This page was generated by a JavaScript file inside WebAssembly
</p>
</body>`;

// Build a new response
let response = new Response(body);

// Add a new header
response.headers.set("x-generated-by", "wasm-workers-server");

return response;
}

// Subscribe to the Fetch event
addEventListener("fetch", event => {
return event.respondWith(reply(event.request));
});
```

1. Save the file and run your worker with `wws`. If you didn't download the `wws` server yet, check our [Getting Started](../start.md) guide.
```bash
wws
⚙️ Loading routes from: .
🗺 Detected routes:
- http://127.0.0.1:8080/
=> index.js (handler: default)
🚀 Start serving requests at http://127.0.0.1:8080
```
1. Finally, open <http://127.0.0.1:8080> in your browser.
## Add a Key / Value store
Wasm Workers allows you to add a Key / Value store to your workers. Read more information about this feature in the [Key / Value store](../features/key-value.md) section.
To add a KV store to your worker, follow these steps:
1. First, create a `counter.js` file. It will access to the KV store through the `Cache` object:
```javascript title="./counter.js"
const CACHE_KEY = "counter";
const reply = (request) => {
let counter = Cache.get("counter") || 0;
counter += 1;
Cache.set("counter", counter);
return new Response(`Counter: ${counter}`);
}
addEventListener("fetch", event => {
event.respondWith(reply(event.request));
});
```
1. Create a `counter.toml` file with the following content. Note the name of the TOML file must match the name of the handler. In this case we have `counter.js` and `counter.toml` in the same folder:
```toml title="./counter.toml"
name = "counter"
version = "1"
[data]
[data.kv]
namespace = "counter"
```
1. Save the file and run your worker with `wws`. If you didn't download the `wws` server yet, check our [Getting Started](../start.md) guide.

```bash
wws
⚙️ Loading routes from: .
🗺 Detected routes:
- http://127.0.0.1:8080/counter
=> counter.js (handler: default)
🚀 Start serving requests at http://127.0.0.1:8080
```

1. Finally, open <http://127.0.0.1:8080/counter> in your browser.

## Other examples

* [Basic](https://github.com/vmware-labs/wasm-workers-server/tree/main/examples/js-basic/handler.js)
* [JSON](https://github.com/vmware-labs/wasm-workers-server/tree/main/examples/js-json/handler.js)
* [Redirect](https://github.com/vmware-labs/wasm-workers-server/tree/main/examples/js-redirect/handler.js)
* [Tic Tac Toe](https://github.com/vmware-labs/wasm-workers-server/tree/main/examples/js-tictactoe/handler.js)
Loading

0 comments on commit c5293a7

Please sign in to comment.