Worker Filesystem
Each worker runs in a sandboxed filesystem. Both the /
path and the current working directory of a worker point to the root of this sandboxed filesystem.
There is no way for a worker to access files outside its own filesystem.
To interact with the worker filesytem, you normally just need to use your regular filesystem apis. The language specific tooling will take care of translating these to invocations of the wasi:filesystem (opens in a new tab) api which is implemented by Golem.
Example
This section assumes that you have a Golem project with an app manifest. If you don't have one yet, please follow the guide and then continue here.
This example will walk you through creating a worker that will interact with its sandboxed filesystem.
Defining the component
We begin by adding a new component to our application:
golem component new rust example:filesystem
Adjust the wit file defining the component so we have a convenient entrypoint. This will just be used to invoke the component, so feel free to name the functions as you like.
diff --git a/components-rust/example-filesystem/wit/example-filesystem.wit b/components-rust/example-filesystem/wit/example-filesystem.wit
index 65b5dda..e56b6e8 100644
--- a/components-rust/example-filesystem/wit/example-filesystem.wit
+++ b/components-rust/example-filesystem/wit/example-filesystem.wit
@@ -3,8 +3,7 @@ package example:filesystem;
// See https://component-model.bytecodealliance.org/design/wit.html for more details about the WIT syntax
interface example-filesystem-api {
- add: func(value: u64);
- get: func() -> u64;
+ run: func();
+ get-contents: func() -> string;
}
world example-filesystem {
Finally we need to adjust the implementation of the component to write a file when invoked:
mod bindings;
use crate::bindings::exports::example::filesystem_exports::example_filesystem_api::Guest;
struct Component;
impl Guest for Component {
fn run() {
std::fs::write("/foobar.txt", "Hello, World!").unwrap()
}
fn get_contents() -> String {
std::fs::read_to_string("/foobar.txt").unwrap()
}
}
bindings::export!(Component with_types_in bindings);
Invoking the worker
Once we have defined the component, we can the deploy the component and invoke a worker using the Golem cli:
golem app deploy example:filesystem
golem worker invoke example:filesystem/test-worker 'example:filesystem-exports/example-filesystem-api.{run}()'
As part of the invocation, the worker performed the side effect of writing a file in its sandboxed filesystem. This file will persist and can be used in all future invocations. For example:
golem worker invoke example:filesystem/test-worker 'example:filesystem-exports/example-filesystem-api.{get-contents}()'
Invocation results in WAVE format:
- "Hello, World!"
Initial File System
This section builds on the project and Golem state created in the example project.
The Initial File System (IFS) refers to all files that are present in the worker filesystem before the worker is started. These can include configuration files, static assets and other things that you want to include with your worker.
The IFS is configured on the level of a component, meaning that all workers created from a given component + version will always start with the
same filesystem. To configure the IFS, include a files
section in your golem.yaml
If you are using profiles in your golem.yaml, you currently have to include the files section in each of your profiles when overriding.
components:
example:filesystem:
template: rust
profiles:
debug:
files:
- sourcePath: ./files/foo.txt
targetPath: /foobar.txt
permissions: read-write
- sourcePath: ./files/bar.txt
targetPath: /bar.txt
permissions: read-only
release:
files:
- sourcePath: ./files/foo.txt
targetPath: /foobar.txt
permissions: read-write
- sourcePath: ./files/bar.txt
targetPath: /bar.txt
permissions: read-only
After deploying the component, any new workers created will have the file /foobar.txt
(and ./foobar.txt
as the worker is starting the root) available to them.
The file /bar.txt
on the other hand is only available for reading. Trying to open the file for writing will fail with a language-dependent error.
echo "I'm already here" > ./files/foobar.txt
golem app deploy example:filesystem
golem worker invoke example:filesystem/test-worker-2 'example:filesystem-exports/example-filesystem-api.{get-contents}()'
Invocation results in WAVE format:
- "I\'m already here\n"
Updating a worker
Updating a worker that uses IFS requires some special consideration depending on the update mode you choose:
- Automatic updates: When using automatic updates the old worker invocations are replayed on top of the new IFS. This means that the worker should produce exactly the same results and side effects as it did with the old IFS. For example, changing the format of a file will work without issues, but changing a file that gets read by the worker and returned to the user will likely lead to divergence. In such cases a manual update might be necessary.
- Manual updates: When using manual updates, you are responsible for saving and restoring the content of files in the worker filesystem. You can
use the
golem:api/save-snapshot
function to persist the files and later restore / migrate them usinggolem:api/load-snapshot
.
Externally accessing worker files
You can use file-server worker bindings to automatically deploy a REST API that allows accessing the files on a worker filesystem.