Skip to content

Commit

Permalink
Implement the component-side hostcalls for KV Store (#430)
Browse files Browse the repository at this point in the history
* match wit and component to trevor's working branch in xqd

* lookup_wait impl for component

* insert and delete

* list impl
  • Loading branch information
computermouth authored Sep 26, 2024
1 parent 5557028 commit c22e3a8
Show file tree
Hide file tree
Showing 4 changed files with 315 additions and 73 deletions.
85 changes: 54 additions & 31 deletions crates/adapter/src/fastly/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2677,6 +2677,21 @@ pub mod fastly_kv_store {
PreconditionFailed,
PayloadTooLarge,
InternalError,
TooManyRequests,
}

impl From<kv_store::KvStatus> for KvError {
fn from(value: kv_store::KvStatus) -> Self {
match value {
kv_store::KvStatus::Ok => Self::Ok,
kv_store::KvStatus::BadRequest => Self::BadRequest,
kv_store::KvStatus::NotFound => Self::NotFound,
kv_store::KvStatus::PreconditionFailed => Self::PreconditionFailed,
kv_store::KvStatus::PayloadTooLarge => Self::PayloadTooLarge,
kv_store::KvStatus::InternalError => Self::InternalError,
kv_store::KvStatus::TooManyRequests => Self::TooManyRequests,
}
}
}

#[export_name = "fastly_kv_store#open"]
Expand Down Expand Up @@ -2735,50 +2750,53 @@ pub mod fastly_kv_store {
pending_handle: PendingObjectStoreLookupHandle,
body_handle_out: *mut BodyHandle,
metadata_out: *mut u8,
metadata_len: *mut usize,
metadata_len: usize,
nwritten_out: *mut usize,
generation_out: *mut u32,
kv_error_out: *mut KvError,
) -> FastlyStatus {
let res = match kv_store::lookup_wait(pending_handle) {
Ok(Some(res)) => res,
Ok(None) => {
Ok((res, status)) => {
unsafe {
*kv_error_out = KvError::NotFound;
*kv_error_out = status.into();
}

return FastlyStatus::OK;
let Some(res) = res else {
return FastlyStatus::OK;
};

res
}
Err(e) => {
unsafe {
// TODO: the wit interface doesn't return any KvError values
*kv_error_out = KvError::Uninitialized;
}

return e.into();
}
};

let max_len = unsafe { *metadata_len };

with_buffer!(
metadata_out,
max_len,
{ res.metadata(u64::try_from(max_len).trapping_unwrap()) },
metadata_len,
{ res.metadata(u64::try_from(metadata_len).trapping_unwrap()) },
|res| {
let buf = handle_buffer_len!(res, metadata_len);
let buf = handle_buffer_len!(res, nwritten_out);

unsafe {
*metadata_len = buf.as_ref().map(Vec::len).unwrap_or(0);
*nwritten_out = buf.as_ref().map(Vec::len).unwrap_or(0);
}

std::mem::forget(buf);
}
);

let body = res.body();
let generation = res.generation();

unsafe {
*body_handle_out = res.body();
*generation_out = res.generation();
*kv_error_out = KvError::Ok;
*body_handle_out = body;
*generation_out = generation;
}

FastlyStatus::OK
Expand Down Expand Up @@ -2839,18 +2857,16 @@ pub mod fastly_kv_store {
kv_error_out: *mut KvError,
) -> FastlyStatus {
match kv_store::insert_wait(pending_body_handle) {
Ok(_) => {
Ok(status) => {
unsafe {
*kv_error_out = KvError::Ok;
*kv_error_out = status.into();
}

FastlyStatus::OK
}

// TODO: the wit interface doesn't return any KvError values
Err(e) => {
unsafe {
// TODO: the wit interface doesn't return any KvError values
*kv_error_out = KvError::Uninitialized;
}

Expand Down Expand Up @@ -2890,17 +2906,16 @@ pub mod fastly_kv_store {
kv_error_out: *mut KvError,
) -> FastlyStatus {
match kv_store::delete_wait(pending_body_handle) {
Ok(_) => {
Ok(status) => {
unsafe {
*kv_error_out = KvError::Ok;
*kv_error_out = status.into();
}

FastlyStatus::OK
}

Err(e) => {
unsafe {
// TODO: the wit interface doesn't return any KvError values
*kv_error_out = KvError::Uninitialized;
}

Expand All @@ -2916,19 +2931,27 @@ pub mod fastly_kv_store {
list_config: *const ListConfig,
pending_body_handle_out: *mut PendingObjectStoreListHandle,
) -> FastlyStatus {
let mask = list_config_mask.into();
let mask = kv_store::ListConfigOptions::from(list_config_mask);

let config = unsafe {
kv_store::ListConfig {
mode: (*list_config).mode.into(),
cursor: {
cursor: if mask.contains(kv_store::ListConfigOptions::CURSOR) {
let len = usize::try_from((*list_config).cursor_len).trapping_unwrap();
Vec::from_raw_parts((*list_config).cursor as *mut _, len, len)
} else {
Vec::new()
},
limit: if mask.contains(kv_store::ListConfigOptions::LIMIT) {
(*list_config).limit
} else {
0
},
limit: (*list_config).limit,
prefix: {
prefix: if mask.contains(kv_store::ListConfigOptions::PREFIX) {
let len = usize::try_from((*list_config).prefix_len).trapping_unwrap();
Vec::from_raw_parts((*list_config).cursor as *mut _, len, len)
Vec::from_raw_parts((*list_config).prefix as *mut _, len, len)
} else {
Vec::new()
},
}
};
Expand Down Expand Up @@ -2957,19 +2980,19 @@ pub mod fastly_kv_store {
kv_error_out: *mut KvError,
) -> FastlyStatus {
match kv_store::list_wait(pending_body_handle) {
Ok(res) => {
Ok((res, status)) => {
unsafe {
*kv_error_out = KvError::Ok;
*body_handle_out = res;
*kv_error_out = status.into();
*body_handle_out = res.unwrap_or(INVALID_HANDLE);
}

FastlyStatus::OK
}

Err(e) => {
unsafe {
// TODO: the wit interface doesn't return any KvError values
*kv_error_out = KvError::Uninitialized;
*body_handle_out = INVALID_HANDLE;
}

e.into()
Expand Down
33 changes: 32 additions & 1 deletion lib/src/component/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use {
super::fastly::api::{http_req, types},
super::fastly::api::{http_req, kv_store::KvStatus, types},
crate::{
config::ClientCertError,
error::{self, HandleError},
Expand All @@ -12,6 +12,7 @@ use {
status::InvalidStatusCode,
uri::InvalidUri,
},
wasmtime_wasi::ResourceTableError,
};

impl types::Error {
Expand Down Expand Up @@ -95,6 +96,12 @@ impl From<http::Error> for types::Error {
}
}

impl From<std::string::FromUtf8Error> for types::Error {
fn from(_: std::string::FromUtf8Error) -> Self {
types::Error::InvalidArgument
}
}

impl From<wiggle::GuestError> for types::Error {
fn from(err: wiggle::GuestError) -> Self {
use wiggle::GuestError::*;
Expand Down Expand Up @@ -146,6 +153,30 @@ impl From<KvStoreError> for types::Error {
}
}

impl From<ResourceTableError> for types::Error {
fn from(err: ResourceTableError) -> Self {
match err {
_ => panic!("{}", err),
}
}
}

impl From<KvStoreError> for KvStatus {
fn from(err: KvStoreError) -> Self {
use KvStoreError::*;
match err {
Uninitialized => panic!("{}", err),
Ok => KvStatus::Ok,
BadRequest => KvStatus::BadRequest,
NotFound => KvStatus::NotFound,
PreconditionFailed => KvStatus::PreconditionFailed,
PayloadTooLarge => KvStatus::PayloadTooLarge,
InternalError => KvStatus::InternalError,
TooManyRequests => KvStatus::TooManyRequests,
}
}
}

impl From<KeyValidationError> for types::Error {
fn from(_: KeyValidationError) -> Self {
types::Error::GenericError
Expand Down
Loading

0 comments on commit c22e3a8

Please sign in to comment.