Current section
Files
Jump to
Current section
Files
src/radish.gleam
import gleam/list
import gleam/float
import gleam/option
import gleam/result
import gleam/otp/actor
import gleam/erlang/process
import radish/resp
import radish/error
import radish/client
import radish/command
import radish/utils.{execute}
pub fn start(host: String, port: Int, timeout: Int) {
use client <- result.then(client.start(host, port, timeout))
use _ <- result.then(
process.try_call(
client,
client.Command(command.hello(3), _, timeout),
timeout,
)
|> result.replace_error(actor.InitFailed(process.Abnormal(
"Failed to say hello",
))),
)
Ok(client)
}
pub fn keys(client, pattern: String, timeout: Int) {
command.keys(pattern)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.Array(array) ->
list.try_map(
array,
fn(item) {
case item {
resp.BulkString(value) -> Ok(value)
_ -> Error(error.RESPError)
}
},
)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
pub fn exists(client, keys: List(String), timeout: Int) {
command.exists(keys)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.Integer(n) -> Ok(n)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
pub fn get(client, key: String, timeout: Int) {
command.get(key)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.SimpleString(str) | resp.BulkString(str) -> Ok(str)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
pub fn mget(client, keys: List(String), timeout: Int) {
command.mget(keys)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.Array(array) ->
list.try_map(
array,
fn(item) {
case item {
resp.BulkString(str) -> Ok(str)
_ -> Error(error.RESPError)
}
},
)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
pub fn append(client, key: String, value: String, timeout: Int) {
command.append(key, value)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.Integer(n) -> Ok(n)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
pub fn set(
client,
key: String,
value: String,
ttl: option.Option(Int),
timeout: Int,
) {
case ttl {
option.None -> command.set(key, value, [])
option.Some(ttl) -> command.set(key, value, [command.PX(ttl)])
}
command.set(key, value, [])
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.SimpleString(str) | resp.BulkString(str) -> Ok(str)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
/// only sets a key if it does not already exist
pub fn set_new(
client,
key: String,
value: String,
ttl: option.Option(Int),
timeout: Int,
) {
case ttl {
option.None -> command.set(key, value, [command.NX])
option.Some(ttl) -> command.set(key, value, [command.NX, command.PX(ttl)])
}
command.set(key, value, [command.NX])
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.SimpleString(str) | resp.BulkString(str) -> Ok(str)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
/// only sets a key if it already exists, returns the old value
pub fn set_existing(
client,
key: String,
value: String,
ttl: option.Option(Int),
timeout: Int,
) {
case ttl {
option.None -> command.set(key, value, [command.XX, command.GET])
option.Some(ttl) ->
command.set(key, value, [command.XX, command.GET, command.PX(ttl)])
}
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.SimpleString(str) | resp.BulkString(str) -> Ok(str)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
pub fn mset(client, kv_list: List(#(String, String)), timeout: Int) {
command.mset(kv_list)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.SimpleString(str) | resp.BulkString(str) -> Ok(str)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
pub fn del(client, keys: List(String), timeout: Int) {
command.del(keys)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.Integer(n) -> Ok(n)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
/// adds 1 to an integer and returns the new value
pub fn incr(client, key: String, timeout: Int) {
command.incr(key)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.Integer(new) -> Ok(new)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
/// adds an arbitrary value to an integer and returns the new value
pub fn incr_by(client, key: String, value: Int, timeout: Int) {
command.incr_by(key, value)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.Integer(new) -> Ok(new)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
/// adds an arbitrary float value to a number and returns the new value
pub fn incr_by_float(client, key: String, value: Float, timeout: Int) {
command.incr_by_float(key, value)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.BulkString(new) ->
float.parse(new)
|> result.replace_error(error.RESPError)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
/// subtracts 1 from an integer and returns the new value
pub fn decr(client, key: String, timeout: Int) {
command.incr(key)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.Integer(new) -> Ok(new)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}
/// subtracts an arbitrary value from an integer and returns the new value
pub fn decr_by(client, key: String, value: Int, timeout: Int) {
command.incr_by(key, value)
|> execute(client, _, timeout)
|> result.map(fn(value) {
case value {
resp.Integer(new) -> Ok(new)
_ -> Error(error.RESPError)
}
})
|> result.flatten
}