Skip to main content

2. Make It Your own

In the next 5 minutes we will take you through making your first changes to a Rust application running in Wasm. If you haven't got the demo running yet, check out the quick start guide.

3. Making it Your Own

Prerequisites

As a reminder, since we'll be editing Rust code, make sure you have Rust installed, and ensure you have a WebAssembly target added to your toolchain. You can add this target with:

bash
rustup target add wasm32-unknown-unknown
bash
rustup target add wasm32-unknown-unknown

Generating a New Actor

Let's see how easy it is to update an application with new code. First we'll generate a new actor project.

bash
cosmo new actor --git https://github.com/cosmonic/awesome-cosmonic --subfolder xkcdgenerator my-xkcd
bash
cosmo new actor --git https://github.com/cosmonic/awesome-cosmonic --subfolder xkcdgenerator my-xkcd

This command generated a git repository in the my-xkcd directory with everything you need to compile and run your actor. Other than the code itself, the most important file here is wasmcloud.toml. This file contains metadata for your project, including the claims, which are a set of capabilities that your actor may use (think of the capability providers mentioned earlier)

claims = ["wasmcloud:httpserver", "wasmcloud:httpclient", "wasmcloud:builtin:numbergen"]
claims = ["wasmcloud:httpserver", "wasmcloud:httpclient", "wasmcloud:builtin:numbergen"]

We have three claims in this actor already: the HTTP server to respond to requests, the HTTP client to get images, and numbergen to generate random numbers.

Compiling and Signing an Actor

Building an actor takes just one command:

bash
cosmo build
bash
cosmo build

This command uses your local toolchain to compile the actor into a WebAssembly module. It then signs your actor.

Launching an Actor Locally

Once again, launching an actor is a single command:

bash
cosmo launch
bash
cosmo launch

All actors run in a host. cosmo launch runs your actors in a local host (and starts a host for you, if one is not already running). Unpacking this, the first time you run cosmo launch we will start wasmCloud on your machine (a new host), then start an actor on that new host!

If you return to the Logic View, you'll see a new actor has appeared in your constellation. It has a similar name to the one that you started with the initial tutorial command. However, you'll notice the new actor has a different icon. The Cosmonic UI provides a visual indicator of whether your components are running on a host managed by Cosmonic.

However, it doesn't matter whether your components are running on a Cosmonic host or a host on your laptop locally. Cosmonic is designed for distributed applications; whether parts of your application are running on a laptop, in a cloud provider's VM, or on a Raspberry Pi is irrelevant!

Connecting an Actor to Capability Providers

You'll also notice that the new actor is not connected to any capability providers. This is because the actor you generated has its own unique identity key, different from the pre-built actor you started with the tutorial command, and links are based on the actor's ID.

To link your new actor to the capability providers, you can simply drag from each of the capability names on the actor to the corresponding provider.

Create Link

As you can see, a modal will open, allowing you to provide custom configuration, but the default values are fine, so you can just click "Create Link."

Detailed Link

Allowing Inbound Traffic

Your new actor is linked up and ready to go! The only remaining step is to create a new wormhole, which is an HTTP ingress point associated with a randomly-generated domain name. Starting from the Logic View once again, click the + Wormhole button.

This will open a new modal where you select which actor to connect to HTTP requests coming from outside Cosmonic. Select your new actor xkcdgenerator (the one without the space) and click "Create Wormhole."

Create wormhole

Now we can click on the new wormhole node that has appeared on the canvas. This will open a side panel with details about your new wormhole. From here, we click the "Access your Wormhole" button to open a new tab. You should see another XKCD comic! This time, the comics are being generated by your new actor that is running locally.

The Flexibility of Distributed Applications

Notice what you didn't do: start any new capability providers. Your new actor is running locally, but it's connected to the capability providers running on Cosmonic. This isn't unique to actors, either; you can also run capability providers locally, and connect them to actors running anywhere!

Updating an Actor

Let's return to the new actor. The source code is in src/lib.rs. Open this file and we can take a look at what this does.

The actor implements a single function handle_request. In this function, we generate a random number, issue an HTTP request to the XKCD API, and return an HTML response (which is rendered by your browser).

The random number is generated in a range, representing the list of comic IDs which were valid at the time this template was first written. This is being done using one of the capability providers which are built into the host that your actor is running on (another is a logging capability). These work the same way (through contracts and claims), but you don't need to explicitly start a provider to access these capabilities.

At the time of writing, 2779 was the latest comic ID. Since some time has passed, you could increase the upper end of the range to the new maximum comic ID. Or, you could restrict the range, or eliminate the randomness altogether and always request the same comic! A personal favorite is #1053.

In your editor, change the logic related to selecting a comic. Feel free to change some of the HTML response as well. For example:

rust
let random_num = random_in_range(1053, 1053).await?; // Sample from the best 😉
rust
let random_num = random_in_range(1053, 1053).await?; // Sample from the best 😉
rust
let body = format!(
r#"
<!DOCTYPE html>
<html>
<head>
<title>Your Not-So-Random XKCD comic</title>
</head>
<body>
<h1>A classic: {}</h1>
<img src="{}"/>
</body>
</html>
"#,
comic.title, comic.img
);
rust
let body = format!(
r#"
<!DOCTYPE html>
<html>
<head>
<title>Your Not-So-Random XKCD comic</title>
</head>
<body>
<h1>A classic: {}</h1>
<img src="{}"/>
</body>
</html>
"#,
comic.title, comic.img
);

Once you've updated your actor's code, you can launch a new version by running:

bash
cosmo launch
bash
cosmo launch

cosmo will take care of replacing your actor with the updated code. If you refresh the tab connected to your wormhole, you'll see the results of your changes! It's that easy to iterate quickly on your ideas.

What else made this work?

This XKCD application used three capabilities: HTTP Server, HTTP Client, and (builtin) numbergen. This allowed our app to receive/reply to HTTP requests through a wormhole and query an external API. Notice the lack of boilerplate details in this code: no ports, no TLS certificates, and yet you were able to make a request and receive your response. Cosmonic believes this is the way applications should be built. In other words, Write the Right Code. Let us handle the rest.

To make more dynamic applications, you'll want to explore more capabilities.

What next?

Now that you have been through a fun example, we recommend looking at serving files over HTTP. Check out our next example app to get started: https://cosmonic.com/docs/to-build/blobby