Host calls
Storage
On this page
A plugin's own key-value bytes, its storage tables, and SQL on an external database.
Generated by tools/gen_api_docs.py; do not edit by hand. See host calls
for how a call is made and how values are encoded. Each example shows the shape of a Wasm
request with its required fields; the values in it are illustrative.
| Call | What it does |
|---|---|
store | Stores a value for this plugin, under a key of its choosing. |
load | Reads one back, or None if it was never stored. |
storage_get | One row of this plugin's table, as JSON text, or None when there is no such row. |
sql_submit | Queues SQL for an external MySQL database -- one a website reads, whose schema the plugin owns; not the plugin's own storage. |
sql_result | A finished batch's outcome, taken: each statement's affected rows as a JSON list, or why it failed (the database's own message, the URL and password taken out). |
storage_put | Inserts or replaces one row. |
storage_put_many | Keeps many rows in one call: each table's in one write of the backend, in the order given. |
storage_outcome | What became of a storage_put_many. |
storage_land | Waits, for a bounded time, for this plugin's bulk writes to land: for a plugin's stop. |
storage_delete | Deletes one row, answering whether there was one. |
storage_scan | Rows whose key starts with prefix, in byte order of the key, after after when given, at most limit (which is at most 1000) of them. |
storage_count | How many rows of the table have a key starting with prefix. |
storage_migrate | Starts moving this plugin's rows from backend from (which must be the one it is on) to to, and answers at once; storage_migration follows it. |
storage_migration | This plugin's latest migration since the server started, or None. |
storage_backend | Which backend this plugin's tables are in: json, sqlite or mysql. |
storage_drop | Drops one of this plugin's own tables: every row in it, at once, in whichever backend it is in. |
store
fn store(plugin: &str, key: &str, value: &[u8]) -> ()
Stores a value for this plugin, under a key of its choosing.
Deliberately bytes and not a document store. A plugin that wants structure brings its own encoding, and the server does not grow a schema it would then have to migrate on behalf of somebody else's data.
Wasm request
| Field | Type | Required |
|---|---|---|
value | string | yes |
key | string | yes |
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value (), encoded as in conventions.
{"call": "store", "value": "{\"x\":1}", "key": "home"}
load
fn load(plugin: &str, key: &str) -> Option<Vec<u8>>
Reads one back, or None if it was never stored.
Wasm request
| Field | Type | Required |
|---|---|---|
key | string | yes |
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Option<Vec<u8>>, encoded as in conventions.
{"call": "load", "key": "home"}
storage_get
fn storage_get(plugin: &str, table: &str, key: &str) -> Result<Option<String>, String>
One row of this plugin's table, as JSON text, or None when there is no such row.
Tables are the storage layer the server owner picks a backend for -- JSON files by
default, SQLite or MySQL when plugins/storage.json says so -- and the plugin never
knows which. Unlike store, every call here answers an error rather than a default:
a database that is down is something the plugin must report, not read as "no rows".
Table names are [a-z0-9_]{1,48}, keys at most 256 bytes; see storage.
Wasm request
| Field | Type | Required |
|---|---|---|
table | string | yes |
key | string | yes |
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<Option<String>, String>, encoded as in conventions. An Err arrives as {"error": "..."}.
{"call": "storage_get", "table": "homes", "key": "home"}
sql_submit
fn sql_submit(plugin: &str, setting: &str, statements: &str) -> Result<u64, String>
Queues SQL for an external MySQL database -- one a website reads, whose schema the
plugin owns; not the plugin's own storage. setting names one of the plugin's own secret
settings holding the mysql:// URL, which the server reads so the plugin never handles it.
statements is a JSON list of {"sql": "...", "params": [...]} (null, numbers, strings,
bools), run in one transaction on a worker. Answers the batch's number at once; its outcome
comes from sql_result. At most 8 batches running and 2000 statements a batch.
For server owners: give the plugin a database user of its own, on a database of its
own -- not the one the storage layer uses, whose rows are every plugin's. A plugin can also
change its own secret settings (setting_set), so this lets an installed plugin open a
connection to any host it names: plugins are code the owner chose to run.
Needs: one of the plugin's own secret settings holding the database URL; a setting that is not secret is refused .
Wasm request
| Field | Type | Required |
|---|---|---|
setting | string | yes |
statements | JSON value, read into the Rust parameter statements: &str; see the doc comment | yes |
Shape and limits, as the router words its errors: "statements should be a list".
Router notes: The plugin is the manifest's name, as for store: a guest cannot read another plugin's tables by naming it. Values cross as JSON and are kept as JSON text. plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<u64, String>, encoded as in conventions. An Err arrives as {"error": "..."}.
{"call": "sql_submit", "setting": "database_url", "statements": "SELECT 1"}
sql_result
fn sql_result(plugin: &str, batch: u64) -> Option<Result<String, String>>
A finished batch's outcome, taken: each statement's affected rows as a JSON list, or why it
failed (the database's own message, the URL and password taken out). None while it runs.
Needs: see sql_submit.
Wasm request
| Field | Type | Required |
|---|---|---|
batch | whole number | yes |
Shape and limits, as the router words its errors: "batch is out of range".
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Option<Result<String, String>>, encoded as in conventions; objects in it carry ok, error. An Err arrives as {"error": "..."}.
{"call": "sql_result", "batch": 1}
storage_put
fn storage_put(plugin: &str, table: &str, key: &str, value: &str) -> Result<bool, String>
Inserts or replaces one row. The value is JSON text, at most 1 MiB.
Wasm request
| Field | Type | Required |
|---|---|---|
table | string | yes |
key | string | yes |
value | JSON value, read into the Rust parameter value: &str; see the doc comment | yes |
Shape and limits, as the router words its errors: "value should be the JSON to keep".
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<bool, String>, encoded as in conventions. An Err arrives as {"error": "..."}.
{"call": "storage_put", "table": "homes", "key": "home", "value": "{\"x\":1}"}
storage_put_many
fn storage_put_many(plugin: &str, tables: &[(String, Vec<(String, String)>)]) -> Result<u64, String>
Keeps many rows in one call: each table's in one write of the backend, in the order given.
At most MAX_PUT_MANY (constants) rows across the tables, values JSON as
storage_put takes them. Checked before anything is kept. For a plugin writing faster than
a row a call can bear. Over the boundary it is a list of values and, per table, a key for
each, so a row kept under several indexes is only sent once.
Answers a ticket once the rows are in the backend's queue, in order with the plugin's other
calls, so it never holds the tick for a commit. What became of them is
storage_outcome's to say, for that ticket and nothing else. An error starting
STORAGE_BUSY (constants) means the backend has fallen behind and these rows were
not taken.
Wasm request
| Field | Type | Required |
|---|---|---|
rows | list | yes |
keys | object | yes |
Shape and limits, as the router words its errors: "rows should be a list of values"; "keys should be an object of key lists"; "a table's keys should be a list".
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<u64, String>, encoded as in conventions. An Err arrives as {"error": "..."}.
{"call": "storage_put_many", "rows": [{"name": "home"}], "keys": {"homes": ["steve:home"]}}
storage_outcome
fn storage_outcome(plugin: &str, ticket: u64) -> crate::StorageOutcome
What became of a storage_put_many. An outcome is told once.
Wasm request
| Field | Type | Required |
|---|---|---|
ticket | whole number, 0 or more | yes |
Shape and limits, as the router words its errors: "ticket should be a whole number".
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value crate::StorageOutcome, encoded as in conventions; objects in it carry state, error.
{"call": "storage_outcome", "ticket": 1}
storage_land
fn storage_land(plugin: &str) -> Result<(), String>
Waits, for a bounded time, for this plugin's bulk writes to land: for a plugin's stop.
Wasm request
No fields besides call.
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<(), String>, encoded as in conventions. An Err arrives as {"error": "..."}.
{"call": "storage_land"}
storage_delete
fn storage_delete(plugin: &str, table: &str, key: &str) -> Result<bool, String>
Deletes one row, answering whether there was one.
Wasm request
| Field | Type | Required |
|---|---|---|
table | string | yes |
key | string | yes |
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<bool, String>, encoded as in conventions. An Err arrives as {"error": "..."}.
{"call": "storage_delete", "table": "homes", "key": "home"}
storage_scan
fn storage_scan(plugin: &str, table: &str, prefix: &str, after: Option<&str>, limit: u32) -> Result<Vec<(String, String)>, String>
Rows whose key starts with prefix, in byte order of the key, after after when given,
at most limit (which is at most 1000) of them.
Wasm request
| Field | Type | Required |
|---|---|---|
limit | whole number | yes |
table | string | yes |
prefix | string | yes |
after | string | no |
Shape and limits, as the router words its errors: "after should be a string or null"; "limit should be 1 to 1000".
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<Vec<(String, String)>, String>, encoded as in conventions. An Err arrives as {"error": "..."}.
{"call": "storage_scan", "limit": 100, "table": "homes", "prefix": ""}
storage_count
fn storage_count(plugin: &str, table: &str, prefix: &str) -> Result<u64, String>
How many rows of the table have a key starting with prefix.
Wasm request
| Field | Type | Required |
|---|---|---|
table | string | yes |
prefix | string | yes |
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<u64, String>, encoded as in conventions. An Err arrives as {"error": "..."}.
{"call": "storage_count", "table": "homes", "prefix": ""}
storage_migrate
fn storage_migrate(plugin: &str, from: &str, to: &str) -> Result<(), String>
Starts moving this plugin's rows from backend from (which must be the one it is on) to
to, and answers at once; storage_migration follows it. Only while an operator
or the console is running one of the plugin's commands: the backend is the server
owner's choice. Until it ends the plugin's writes are refused; once every table's count
and checksum match on both sides, to becomes the plugin's backend.
Needs: an operator (level 3) or the console running one of the plugin's own commands at that moment (see the doc comment).
Wasm request
| Field | Type | Required |
|---|---|---|
from | string | yes |
to | string | yes |
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<(), String>, encoded as in conventions; objects in it carry started. An Err arrives as {"error": "..."}.
{"call": "storage_migrate", "from": "json", "to": "sqlite"}
storage_migration
fn storage_migration(plugin: &str) -> Result<Option<crate::storage::Migration>, String>
This plugin's latest migration since the server started, or None.
Wasm request
No fields besides call.
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<Option<crate::storage::Migration>, String>, encoded as in conventions; objects in it carry from, to, state, error, tables, rows. An Err arrives as {"error": "..."}.
{"call": "storage_migration"}
storage_backend
fn storage_backend(plugin: &str) -> Result<String, String>
Which backend this plugin's tables are in: json, sqlite or mysql.
Wasm request
No fields besides call.
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<String, String>, encoded as in conventions. An Err arrives as {"error": "..."}.
{"call": "storage_backend"}
storage_drop
fn storage_drop(plugin: &str, table: &str) -> Result<bool, String>
Drops one of this plugin's own tables: every row in it, at once, in whichever backend it is in. Answers whether it had any rows. What a wipe does to the tables that belong to one world, without walking them a page at a time. Refused while the plugin is migrating, like any write.
Wasm request
| Field | Type | Required |
|---|---|---|
table | string | yes |
Router notes: plugin is never sent by a Wasm guest: the server fills it in from the manifest name.
Reply: {"ok": ...} holding the Rust return value Result<bool, String>, encoded as in conventions. An Err arrives as {"error": "..."}.
{"call": "storage_drop", "table": "homes"}
From docs/api/reference/host-calls/storage.md in the RustMC repository at bbd81209ad.