Redis Storage
Spin provides an interface for you to read and write the Redis key/value store, and to publish Redis pub-sub messages.
Why do I need a Spin interface? Why can't I just use my language's Redis library?
The current version of the WebAssembly System Interface (WASI) doesn’t provide a sockets interface, so Redis libraries that depend on sockets can’t be built to Wasm. The Spin interface means Wasm modules can bypass this limitation by asking Spin to make the Redis connection on their behalf.
Using Redis From Applications
The Spin SDK surfaces the Spin Redis interface to your language. The set of operations is common across all SDKs:
Operation | Parameters | Returns | Behavior |
---|---|---|---|
open | address | connection resource | Opens a connection to the specified Redis instance. The host must be listed in allowed_outbound_hosts . Other operations must be called through a connection. (Exception: for JavaScript, do not call open , and pass the address to each data operation - see the language guides below.) |
Single value operations | |||
get | key | bytes | Returns the value of key . If the key does not exist, returns a zero-length array. |
set | key, bytes | - | Sets the value of key , overwriting any existing value. |
incr | key | integer | Increments the value at key by 1. If the key does not exist, its value is set to 0 first (and immediately incremented to 1). If the current value isn’t an integer, or a string that represents an integer, it errors and the value is not changed. |
del | list of keys | - | Removes the specified keys. Keys that don’t exist are ignored (they do not cause an error). |
Set value operations | |||
sadd | key, list of strings | integer | Adds the strings to the set of values of key , and returns the number of newly added values. If the key does not exist, its value is set to the set of values |
smembers | key | list of strings | Returns the set of values of key . if the key does not exist, this is an empty set. |
srem | key, list of strings | integer | Removes the strings from the set of values of key , and returns the number of newly removed values. If the key does not exist, this does nothing. |
Pub-sub operations | |||
publish | channel, bytes | - | Publishes a message to the specified channel, with the specified payload bytes. |
General operations | |||
execute | command, list of argument values | list of results | Executes the specified command with the specified arguments. This is a general-purpose ‘escape hatch’ if you need a command that isn’t covered by the built-in operations. |
The exact detail of calling these operations from your application depends on your language:
Want to go straight to the reference documentation? Find it here.
Redis functions are available in the spin_sdk::redis
module.
To access a Redis instance, use the Connection::open
function.
let connection = spin_sdk::redis::Connection::open(&address)?;
You can then call functions on the Connection
to work with the Redis instance:
connection.set("my-key", &"my-value".into());
let data = connection.get("my-key")?;
For full details of the Redis API, see the Spin SDK reference documentation;
General Notes
- Keys are of type
&str
. - Bytes parameters are of type
&[u8]
and return values areVec<u8>
. - Numeric return values are of type
i64
. - All functions wrap the return in
anyhow::Result
.
get
Operation
- This returns a
Result<Option<Vec<u8>>>
. If the key is not found, the return value isOk(None)
.
del
Operation
- The list of keys is passed as
&[String]
.
Set Operations
- List arguments are passed as
&[String]
and returned asVec<String>
.
execute
Operation
- The arguments and results are enums, representing integers, binary payloads, and (for results) status and nil values.
You can find a complete Rust code example for using outbound Redis from an HTTP component in the Spin repository on GitHub. Please also see this, related, outbound Redis (using Rust) section.
Want to go straight to the reference documentation? Find it here.
Redis functions are available on the Redis
object. The function names match the operations above, but you must pass the Redis instance address to each operation as its first parameter. For example:
import {Redis} from "@fermyon/spin-sdk"
const value = Redis.get(address, key);
General Notes
- The
spinSdk
object is always available at runtime. Code checking and completion are available in TypeScript at design time if the module imports anything from the@fermyon/spin-sdk
package. - Address and key parameters are strings.
- Bytes parameters and return values are buffers (TypeScript
ArrayBuffer
). - Lists are passed and returned as arrays.
- If a Spin SDK function fails, it throws an Error.
execute
Operation
- The arguments and results can be either numbers or buffers. (In TypeScript they are union types, e.g.
BigInt | ArrayBuffer
.)
You can find a complete TypeScript example for using outbound Redis from an HTTP component in the JavaScript SDK repository on GitHub. Please also see this, related, outbound Redis (using TypeScript) section.
Want to go straight to the reference documentation? Find it here.
Redis functions are available in the redis
module. The function names are prefixed redis_
. You must pass the Redis instance address to each operation as its first parameter. For example:
from spin_sdk import redis
with redis.open("redis://localhost:6379") as db:
val = db.get("test")
General Notes
- Address and key parameters are strings (
str
). - Bytes parameters and return values are
bytes
. (You can pass literal strings using theb
prefix, e.g.redis_set(address, key, b"hello")
.) - Numeric return values are of type
int64
. - Lists are passed and returned as Python lists.
- Errors are signalled through exceptions.
You can find a complete Python code example for using outbound Redis from an HTTP component in the Python SDK repository on GitHub. Please also see this, related, outbound Redis (using Python) section.
Want to go straight to the reference documentation? Find it here.
Redis functions are available in the github.com/fermyon/spin/sdk/go/v2/redis
package. See Go Packages for reference documentation. The function names are TitleCased. For example:
import (
"github.com/fermyon/spin/sdk/go/v2/redis"
)
rdb := redis.NewClient(addr)
payload, err := rdb.Get(key)
General Notes
- Key parameters are strings.
- Bytes parameters are byte slices (
[]byte
). - Lists are passed as slices. For example,
redis.Del
takes the keys to delete as a[]string
. - Errors are return through the usual Go multiple return values mechanism.
execute
Operation
- The arguments are passed as
[]redis.RedisParameter
. You can constructRedisParameter
instances around aninterface{}
but must provide aKind
. For example,hello := redis.RedisParameter{Kind: redis.RedisParameterKindBinary, Val: []byte("hello")}
. - The results are returned as
[]redis.Result
. You can use theKind
member ofredis.Result
to interpret theVal
.
You can find a complete TinyGo example for using outbound Redis from an HTTP component in the Spin repository on GitHub. Please also see this, related, outbound Redis (using TinyGo) section.
Granting Network Permissions to Components
By default, Spin components are not allowed to make outgoing network requests, including Redis. This follows the general Wasm rule that modules must be explicitly granted capabilities, which is important to sandboxing. To grant a component permission to make network requests to a particular host, use the allowed_outbound_hosts
field in the component manifest, specifying the host and allowed port:
[component.uses-redis]
allowed_outbound_hosts = ["redis://redis.example.com:6379"]
Configuration-Based Permissions
You can use application variables in the allowed_outbound_hosts
field. However, this feature is not yet available on Fermyon Cloud.