diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 77b2cd90b..435a01eae 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,217 +1,155 @@ -## Running integration tests +# Golem development -Install [cargo make](https://github.com/sagiegurari/cargo-make) +To work on **Golem** you need to install the following tools: -```shell -cargo install --force cargo-make -``` +- Latest **stable** rust compiler + - use [rustup](https://rustup.rs/) + - then run `rustup update stable` + - and `rustup default stable` +- Install the `wasm32-wasip1` target + - `rustup target add wasm32-wasip1` +- Install [cargo-make](https://github.com/sagiegurari/cargo-make) + - `cargo install --force cargo-make` +- The [prost crate](https://crates.io/crates/prost) requires `protoc` to be installed. + - Requires **version 28** or later + - `brew install protobuf` on OSX + - Otherwise follow the [official instructions](https://github.com/protocolbuffers/protobuf#protobuf-compiler-installation) -runs all unit tests, worker executor tests and integration tests +To be able to run all integration tests: + - Install redis + - `brew install redis` on OSX + - Install [docker](https://www.docker.com) (for running PostgreSQL container in tests) -```shell -cargo make test -``` +To be able to run all services with `cargo-make run` with a merged log view: +- Install [lnav](https://lnav.org) + - `brew install lnav` on OSX +- Install [nginx](https://nginx.org) + - `brew install nginx` on OSX -runs unit tests only +Everything else is managed by `cargo-make`. -```shell -cargo make unit-tests -``` +## Development workflow -runs worker executor tests only +### Building +To compile everything use ```shell -cargo make integration-tests +cargo make build ``` - -runs CLI tests only +It is recommended to do a full build before starting working on Golem and opening it with an IDE. During development it is usually enough to recompile only the crate you are working on, for example: ```shell -cargo make cli-tests +cargo build -p golem-worker-service-base ``` -runs sharding integration tests only +#### If cargo runs out of memory +Depending on the number of CPU cores and available memory, building everything can use a lot of memory. If cargo runs out of memory or just uses too much, you can limit the number of parallel jobs by providing a cargo `config.toml` file, for example: -```shell -cargo make sharding-tests +```toml +[build] +jobs = 4 ``` -## Running Benchmarks +in `~/.cargo/config.toml`. For other options and possibilities check [the cargo documentation](https://doc.rust-lang.org/cargo/reference/config.html). -1. Raise PR -2. Reviewer or author of PR can run benchmarks by typing in a PR comment as follows -```shell - /run-benchmark -``` +### Running tests -3. For all new benchmark types (meaning, those for which there is no baseline to compare), it should generate a report as below, as a PR comment +Tests are using the [test-r library](https://test-r.vigoo.dev). -## Benchmark Report -| Benchmark Type | Cluster Size | Size | Length | Avg Time | -|---------------|--------------|------|--------|----------| -| benchmark_cold_start_large.json | 3 | 10 | 100 | 201.255108ms | -| benchmark_cold_start_large_no_compilation.json | 3 | 10 | 100 | 123.000794122s | -| benchmark_cold_start_medium.json | 3 | 10 | 100 | 121.566283ms | -| benchmark_cold_start_medium_no_compilation.json | 3 | 10 | 100 | 178.508111048s | -| benchmark_cold_start_small.json | 3 | 10 | 100 | 75.379351ms | -| benchmark_cold_start_small_no_compilation.json | 3 | 10 | 100 | 423.142651ms | -| benchmark_durability_overhead.json | 3 | 10 | 100 | 57.51445ms | -| benchmark_latency_large.json | 3 | 10 | 100 | 61.586289ms | -| benchmark_latency_medium.json | 3 | 10 | 100 | 60.646373ms | -| benchmark_latency_small.json | 3 | 10 | 100 | 54.76123ms | -| benchmark_suspend_worker.json | 3 | 10 | 100 | 10.03030193s | - -RunID: 9435476881 - -4. The underlying data used to created the above report will be automatically pushed back to the PR branch -5. If there exists a baseline to compare for the benchmark type, then a comparison report will be generated for those benchmarks -6. If there is no need to compare with any baseline, regardless of a baseline exist or not, then simply run - -```bash - -/run-benchmark-refresh +During development you can run the involved tests in the usual ways: from the IDE, or using `cargo test` command selecting a specific crate and test module, for example: +```shell +cargo test -p golem-worker-executor-base api::promise -- --report-time ``` -7. Refresh message can be useful in the event of comparison failures (Example: A failure due to schema mismatch especially when a developer refactor the benchmark code itself) - -## Starting all services locally - -There is a simple `cargo make run` task that starts all the debug executables of the services locally, using the default configuration. The prerequisites are: - -- `nginx` installed (on OSX can be installed with `brew install nginx`) -- `redis` installed (on OSX can be installed with `brew install redis`) -- `lnav` installed (on OSX can be installed with `brew install lnav`) - -The `cargo make run` command will start all the services and show a unified view of the logs using `lnav`. Quitting `lnav` kills the spawned processes. - -## Local Testing using Docker containers - -To spin up services using the latest code - -```bash -# Clone golem -cd golem -# Find more info below if you are having issues running this command(example: Running from MAC may fail) -# Target has to be x86_64-unknown-linux-gnu or aarch64-unknown-linux-gnu-gcc -cargo build --release --target x86_64-unknown-linux-gnu +#### Running all unit tests +To run all unit tests use -docker compose -f docker-compose-sqlite.yaml up --build +```shell +cargo make unit-tests ``` -To start the service without a rebuild - -```bash - -docker compose -f docker-compose-sqlite.yaml up +#### Running all worker executor tests +The **worker executor tests** are testing the Golem Worker Executor standalone without any of the other services. These tests require `redis`. To run all of them use +```shell +cargo make worker-executor-tests ``` -To compose down, - -```bash - -docker compose -f docker-compose-sqlite.yaml down +As there are many of these tests, they are organized into **groups** that are executed in parallel on CI. You can run only a specific group with cargo make, for example: +```shell +cargo make worker-executor-tests-group1 ``` -To compose down including persistence volume - -```bash +#### Running all integration tests +The **integration tests** are starting up several Golem services and testing them together. These tests also require `docker` and `redis` to be available. -docker compose -f docker-compose-sqlite.yaml down -v +To run all integration tests use +```shell +cargo make integration-tests ``` -Note that, if you are using MAC, the persistence volumes may be present in the Linux VM. You can inspect this using the following command: - -```bash - -docker run -it --rm --privileged --pid=host alpine:latest nsenter -t 1 -m -u -n -i sh +#### Running all the CLI tests +The **CLI tests** are similar to the integration tests but interact with the running services only through the Golem CLI application. -# As an example: cd /var/lib/docker/volumes/golem-services_redis_data/_data -/var/lib/docker/volumes/golem-services_redis_data/_data # ls -lrt -total 4 --rw------- 1 999 ping 3519 Jan 19 02:32 dump.rdb -/var/lib/docker/volumes/golem-services_redis_data/_data # +To run all CLI tests use +```shell +cargo make cli-tests ``` -If you have issues running the above cargo build command, then read on: +#### Using a debugger +When using a debugger with the tests, make sure to pass the `--nocapture` option to the test runner, otherwise the debugger will not be usable (when capturing is on, the test framework spawns child processes to run the actual tests). -Make sure to do `docker-compose pull` next time to make sure you are pulling the latest images than the cached ones +### Updating the REST API +Golem **generates OpenAPI specs** from the Rust code (using the [poem-openapi crate](https://crates.io/crates/poem-openapi), and the generated OpenAPI yaml file is also stored in the repository and a Rust Client crate is generated from it, used by the CLI app and also published into crates.io. -### Cargo Build +When changing anything that affects the user facing REST API, this YAML needs to be explicitly regenerated. If this does not happen, the CI process will fail and ask for doing it. -### MAC +To regenerate the OpenAPI spec use -If you are running ` cargo build --target ARCH-unknown-linux-gnu` (cross compiling to Linux) from MAC, you may encounter -some missing dependencies. If interested, refer, https://github.com/messense/homebrew-macos-cross-toolchains +```shell +cargo make generate-openapi +``` -### Intel MAC +### Updating the config files +Service config files are also generated from code similarly to OpenAPI specs. When changing any of the service configuration data types, they have to be regeneraetd otherwise the CI process fails and asks for doing it. -Typically, the following should allow you to run it successfully. +To regenerate these files, use -```bash -brew tap messense/macos-cross-toolchains -brew install messense/macos-cross-toolchains/x86_64-unknown-linux-gnu -# If openssl is not in system -# brew install openssl -export OPENSSL_DIR=$(brew --prefix openssl) -export CC_X86_64_UNKNOWN_LINUX_GNU=x86_64-unknown-linux-gnu-gcc -export CXX_X86_64_UNKNOWN_LINUX_GNU=x86_64-unknown-linux-gnu-g++ -export AR_X86_64_UNKNOWN_LINUX_GNU=x86_64-unknown-linux-gnu-ar -export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=x86_64-unknown-linux-gnu-gcc +```shell +cargo make generate-configs ``` -From the root of the project +### Preparing the pull request +Golem CI checks the pull requests with `rustfmt` and `cargo clippy`. To make sure these checks pass, before opening a pull request run -```bash -rustup target add x86_64-unknown-linux-gnu -cargo build --release --target x86_64-unknown-linux-gnu --package golem-shard-manager -cargo build --release --target x86_64-unknown-linux-gnu --package golem-component-service -cargo build --release --target x86_64-unknown-linux-gnu --package golem-worker-service -cargo build --release --target x86_64-unknown-linux-gnu --package golem-component-compilation-service -cargo build --release --target x86_64-unknown-linux-gnu --package golem-worker-executor +```shell +cargo make fix ``` -### ARM MAC +and fix any possible errors and warnings reported by it. -Typically, the following should allow you to run it successfully. +## Running Golem locally -```bash -brew tap messense/macos-cross-toolchains -brew install aarch64-unknown-linux-gnu -# If openssl is not in system -# brew install openssl -export OPENSSL_DIR=$(brew --prefix openssl) -export CC_AARCH64_UNKNOWN_LINUX_GNU=aarch64-unknown-linux-gnu-gcc -export CXX_AARCH64_UNKNOWN_LINUX_GNU=aarch64-unknown-linux-gnu-g++ -export AR_AARCH64_UNKNOWN_LINUX_GNU=aarch64-unknown-linux-gnu-ar -export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-unknown-linux-gnu-gcc -``` +There are two ways now to run Golem locally: + +### Using cargo make run -From the root of the project +By running -```bash -rustup target add aarch64-unknown-linux-gnu -cargo build --release --target aarch64-unknown-linux-gnu --package golem-shard-manager -cargo build --release --target aarch64-unknown-linux-gnu --package golem-component-service -cargo build --release --target aarch64-unknown-linux-gnu --package golem-worker-service -cargo build --release --target aarch64-unknown-linux-gnu --package golem-component-compilation-service -cargo build --release --target aarch64-unknown-linux-gnu --package golem-worker-executor +```shell +cargo make run ``` -### LINUX +all the services are going to be built and started as individual native processes, configured to communicate with each other. Beside that, an `nginx` process is going to be started to unify the various processes' HTTP APIs, and `lnav` is started to merge their logs. -From the root of the project +### Using the Single Golem Executable -```bash -rustup target add x86_64-unknown-linux-gnu -cargo build --release --target x86_64-unknown-linux-gnu --package golem-shard-manager -cargo build --release --target x86_64-unknown-linux-gnu --package golem-component-service -cargo build --release --target x86_64-unknown-linux-gnu --package golem-worker-service -cargo build --release --target x86_64-unknown-linux-gnu --package golem-component-compilation-service -cargo build --release --target x86_64-unknown-linux-gnu --package golem-worker-executor -``` +Golem now contains a **single executable** crate, called `golem`, that links all the services into a single binary. This binary is built using a regular `cargo make build` run and can be executed with +```shell +cargo run -p golem +``` diff --git a/README.md b/README.md index 05f5f64df..e5e8c1dd2 100644 --- a/README.md +++ b/README.md @@ -4,45 +4,8 @@ This repository contains Golem - a set of services enable you to run WebAssembly components in a distributed cloud environment. -See [Golem Cloud](https://golem.cloud) for more information. +## Getting started with Golem +See [Golem Cloud](https://golem.cloud) for more information, and [the Golem Developer Documentation](https://learn.golem.cloud) for getting started. -## Getting Started - -It is possible to start using Golem locally by using our published Docker containers. Please refer to the document link below on how to get golem OSS running using docker. -https://learn.golem.cloud/docs/quickstart#setting-up-golem - -Once you have Golem running locally, you can use `golem-cli` to interact with Golem services. - -```bash - -cargo install golem-cli - -# component is your compiled code written in Rust, C, etc -# https://learn.golem.cloud/docs/building-templates helps you write some code and create a component - as an example -golem-cli component add --compnent-name - -# Now we need a worker corresponding from component, that can execute one of the functions in component -# If worker doesn't exist, it is created on the fly whey you invoke a function in component -golem-cli worker invoke-and-await --component-name --worker-name --function golem:it/api.{add-item} --parameters '[{"product-id" : "foo", "name" : "foo" , "price" : 10, "quantity" : 1}]' - -``` - -Internally, it is as simple as `golem-cli` using `golem-client` sending requests to Golem Services hosted in Docker container. -Therefore, you can see what's going on and troubleshoot things by inspecting docker containers. - -``` - - -+-----------------------+ +-----------------------+ -| | | | -| Use golem-cli | ---> | Golem Services | -| | | hosted in | -| commands | | Docker container | -| (Send Requests) | | | -+-----------------------+ +-----------------------+ - -``` - - -## Compiling Golem locally +## Developing Golem Find details in the [contribution guide](CONTRIBUTING.md) about how to compile the Golem services locally. diff --git a/golem-cli/Cargo.toml b/golem-cli/Cargo.toml index 1192f9ddc..f5d556fc9 100644 --- a/golem-cli/Cargo.toml +++ b/golem-cli/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" license = "Apache-2.0" homepage = "https://golem.cloud/" repository = "https://github.com/golemcloud/golem" -readme = "README.md" description = "Command line interface for Golem." autotests = false @@ -26,7 +25,9 @@ harness = false golem-client = { path = "../golem-client", version = "=0.0.0" } golem-common = { path = "../golem-common", version = "=0.0.0", default-features = false } golem-rib = { path = "../golem-rib", version = "=0.0.0", default-features = false } -golem-wasm-ast = { path = "../wasm-ast", version = "=0.0.0", default-features = false, features = ["analysis"] } +golem-wasm-ast = { path = "../wasm-ast", version = "=0.0.0", default-features = false, features = [ + "analysis", +] } golem-wasm-rpc = { path = "../wasm-rpc", version = "=0.0.0", default-features = false } golem-wasm-rpc-stubgen = { path = "../wasm-rpc-stubgen", version = "=0.0.0" } diff --git a/golem-cli/README.md b/golem-cli/README.md deleted file mode 100644 index b837a1370..000000000 --- a/golem-cli/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# golem-cli - -Command line interface for [Golem OSS](https://golem.cloud). - -For Golem Cloud version client see [Golem Cloud CLI](https://github.com/golemcloud/golem-cloud-cli). - -## Installation - -To install `golem-cli` you currently need to use `cargo`, Rust's build tool. - -To get `cargo` on your system, we recommend to use [rustup](https://rustup.rs/): - -```shell -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -rustup install stable -rustup default stable -``` - -Another external dependency is `protobuf`, with a minimum version of `3.15`, -which can be installed as described on http://google.github.io/proto-lens/installing-protoc.html. On macOS, you can install it with Homebrew: - -```shell -brew install protobuf -``` - -Then you can install `golem-cli` with the following command: - -```shell -cargo install golem-cli -``` - -## More information - -Please check the [Golem Cloud developer documentation portal](https://learn.golem.cloud) to learn more about how to get started with _Golem Cloud_! - -## Contributing - -Find details [here](CONTRIBUTING.md) diff --git a/wasm-rpc-stubgen/README.md b/wasm-rpc-stubgen/README.md index ffd44d10d..b6a65efb8 100644 --- a/wasm-rpc-stubgen/README.md +++ b/wasm-rpc-stubgen/README.md @@ -1,128 +1,4 @@ # golem-wasm-rpc-stubgen -The `golem-wasm-rpc-stubgen` is a CLI tool to generate the RPC stubs from a component's WIT definition. - -## Generate - -```shell -Usage: wasm-rpc-stubgen generate [OPTIONS] --source-wit-root --dest-crate-root - -Options: - -s, --source-wit-root - -d, --dest-crate-root - -w, --world - --stub-crate-version [default: 0.0.1] - --wasm-rpc-path-override - -h, --help Print help - -V, --version Print version -``` - -- `source-wit-root`: The root directory of the component's WIT definition to be called via RPC -- `dest-crate-root`: The target path to generate a new stub crate to -- `world`: The world name to be used in the generated stub crate. If there is only a single world in the source root - package, no need to specify. -- `stub-crate-version`: The crate version of the generated stub crate -- `wasm-rpc-path-override`: The path to the `wasm-rpc` crate to be used in the generated stub crate. If not specified, - the latest version of `wasm-rpc` will be used. - -The command creates a new Rust crate that is ready to be compiled with - -```shell -cargo component build --release -``` - -The resulting WASM component implements the **stub interface** corresponding to the source interface, found in the -target directory's -`wit/stub.wit` file. This WASM component is to be composed together with another component that calls the original -interface via WASM RPC. - -## Build - -``` -Usage: wasm-rpc-stubgen build [OPTIONS] --source-wit-root --dest-wasm --dest-wit-root - -Options: - -s, --source-wit-root - --dest-wasm - --dest-wit-root - -w, --world - --stub-crate-version [default: 0.0.1] - --wasm-rpc-path-override - -h, --help Print help - -V, --version Print version -``` - -- `source-wit-root`: The root directory of the component's WIT definition to be called via RPC -- `dest-wasm`: The name of the stub WASM file to be generated -- `dest-wit-root`: The directory name where the generated WIT files should be placed -- `world`: The world name to be used in the generated stub crate. If there is only a single world in the source root - package, no need to specify. -- `stub-crate-version`: The crate version of the generated stub crate -- `wasm-rpc-path-override`: The path to the `wasm-rpc` crate to be used in the generated stub crate. If not specified, - the latest version of `wasm-rpc` will be used. It needs to be an **absolute path**. - -## Add stub WIT dependency - -```shell -Usage: wasm-rpc-stubgen add-stub-dependency [OPTIONS] --stub-wit-root --dest-wit-root - -Options: - -s, --stub-wit-root - -d, --dest-wit-root - -o, --overwrite - -u, --update-cargo-toml - -h, --help Print help - -V, --version Print version -``` - -The command merges a generated RPC stub as a WIT dependency into an other component's WIT root. - -- `stub-wit-root`: The WIT root generated by either `generate` or `build` command -- `dest-wit-root`: The WIT root of the component where the stub should be added as a dependency -- `overwrite`: This command would not do anything if it detects that it would change an existing WIT file's contents at - the destination. With this flag, it can be forced to overwrite those files. -- `update-cargo-toml`: Enables updating the Cargo.toml file in the parent directory of `dest-wit-root` with the copied dependencies. -- -## Compose the stub with the caller component - -```shell -Usage: wasm-rpc-stubgen compose --source-wasm --stub-wasm --dest-wasm - -Options: - --source-wasm - --stub-wasm - --dest-wasm - -h, --help Print help - -V, --version Print version -``` - -The command composes a caller component's WASM (which uses the generated stub to call a remote worker) with the -generated stub WASM, writing out a composed WASM which no longer depends on the stub interface, ready to use. - -- `source-wasm`: The WASM file of the caller component -- `stub-wasm`: The WASM file of the generated stub. Multiple stubs can be listed. -- `dest-wasm`: The name of the composed WASM file to be generated - - -## Initialize cargo make tasks for a workspace - -```shell -Usage: wasm-rpc-stubgen initialize-workspace [OPTIONS] --targets --callers - -Options: - --targets - List of subprojects to be called via RPC - --callers - List of subprojects using the generated stubs for calling remote workers - --wasm-rpc-path-override -``` - -When both the target and the caller components are in the same Cargo workspace, this command can initialize a `cargo-make` file with dependent tasks -performing the stub generation, WIT merging and WASM composition. - -Once the workspace is initialized, the following two commands become available: - -```shell -cargo make build-flow -cargo make release-build-flow -``` +The `golem-wasm-rpc-stubgen` is a library and CLI tool to generate the RPC stubs from a component's WIT definition +and handle Golem's application manifests. diff --git a/wasm-rpc/README.md b/wasm-rpc/README.md index 970a19ba3..0da86db3e 100644 --- a/wasm-rpc/README.md +++ b/wasm-rpc/README.md @@ -18,19 +18,24 @@ The `golem-wasm-rpc` crate can be both used in host and guest environments: To compile the host version: ```shell -cargo build -p wasm-rpc --no-default-features --features host +cargo build -p golem-wasm-rpc --no-default-features --features host ``` To compile the guest version, has minimal dependencies and feature set to be used in generated stubs: ```shell -cargo component build -p wasm-rpc --no-default-features --features stub +cargo component build -p golem-wasm-rpc --no-default-features --features stub ``` ## Feature flags - `arbitrary` adds an `Arbitrary` instance for `Value` +- `bincode` adds Bincode codecs for some types +- `host-bindings` enables WIT-generated types for wasmtime hosts - `json` adds conversion functions for mapping of a WIT value and type definition to/from JSON +- `poem_openapi` adds poem OpenAPI type class instances for some of the types - `protobuf` adds the protobuf message types +- `serde` adds serde JSON serialization for some of the types +- `text` enables `wasm-wave` based text representation for values - `wasmtime` adds conversion to `wasmtime` `Val` values -- `host` enables all features: `arbitrary`, `json`, `protobuf`, `typeinfo`, and `wasmtime` +- `host` enables all features: `arbitrary`, `bincode`, `host-bindings`, `json`, `poem_openapi`, `protobuf`, `serde`, `text`, `typeinfo`, and `wasmtime` - `stub` is to be used in generated WASM stubs and disables all features, and generates guest bindings instead of host bindings