Skip to content

Commit

Permalink
Added hostcalls for the new builder api hostcalls (#427)
Browse files Browse the repository at this point in the history
* bring over changes from old branch

* Fix the declaration for lookup-result methods in trappable_imports

* start fleshing out builder api

* complete port from the old branch

* more kv store hostcalls, although linkage seems to be failing

* open, list, insert, more or less working, need more work on error handling

* fix up errors for inserts, compiles clean

* finished error reporting for deletes

* everything but ttl and regression tests

* all tests pass, but infinite recursion when deleting in delete

* fixed list ttl deletion, all tests pass

* fix for old sdk on new hostcalls

* clippy

* add base64 to the cargo.lock

* Added in the OOB check

* write out metadata length, even on failure

* cleanups as per @ulyssa

* added unit tests for kv store hostcalls

* Implement the component-side hostcalls for KV Store (#430)

* match wit and component to trevor's working branch in xqd

* lookup_wait impl for component

* insert and delete

* list impl

* re-make adapter

---------

Co-authored-by: Trevor Elliott <[email protected]>
  • Loading branch information
computermouth and elliottt authored Sep 27, 2024
1 parent c9ad383 commit 3fa4243
Show file tree
Hide file tree
Showing 23 changed files with 1,999 additions and 196 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cli/tests/trap-test/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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
1 change: 1 addition & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ wasmtime-wasi = { workspace = true }
wasmtime-wasi-nn = { workspace = true }
wat = { workspace = true }
wiggle = { workspace = true }
base64 = { workspace = true }

[dev-dependencies]
tempfile = "3.6.0"
Expand Down
74 changes: 74 additions & 0 deletions lib/compute-at-edge-abi/compute-at-edge.witx
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@
)
)

;; NOTE: These are deprecated, use the fastly_kv_store hostcalls
(module $fastly_object_store
(@interface func (export "open")
(param $name string)
Expand Down Expand Up @@ -820,6 +821,79 @@
)
)

(module $fastly_kv_store
(@interface func (export "open")
(param $name string)
(result $err (expected $kv_store_handle (error $fastly_status)))
)

(@interface func (export "lookup")
(param $store $kv_store_handle)
(param $key string)
(param $lookup_config_mask $kv_lookup_config_options)
(param $lookup_configuration (@witx pointer $kv_lookup_config))
(param $handle_out (@witx pointer $kv_store_lookup_handle))
(result $err (expected (error $fastly_status)))
)

(@interface func (export "lookup_wait")
(param $handle $kv_store_lookup_handle)
(param $body_handle_out (@witx pointer $body_handle))
(param $metadata_buf (@witx pointer (@witx char8)))
(param $metadata_buf_len (@witx usize))
(param $nwritten_out (@witx pointer (@witx usize)))
(param $generation_out (@witx pointer u32))
(param $kv_error_out (@witx pointer $kv_error))
(result $err (expected (error $fastly_status)))
)

(@interface func (export "insert")
(param $store $kv_store_handle)
(param $key string)
(param $body_handle $body_handle)
(param $insert_config_mask $kv_insert_config_options)
(param $insert_configuration (@witx pointer $kv_insert_config))
(param $handle_out (@witx pointer $kv_store_insert_handle))
(result $err (expected (error $fastly_status)))
)

(@interface func (export "insert_wait")
(param $handle $kv_store_insert_handle)
(param $kv_error_out (@witx pointer $kv_error))
(result $err (expected (error $fastly_status)))
)

(@interface func (export "delete")
(param $store $kv_store_handle)
(param $key string)
(param $delete_config_mask $kv_delete_config_options)
(param $delete_configuration (@witx pointer $kv_delete_config))
(param $handle_out (@witx pointer $kv_store_delete_handle))
(result $err (expected (error $fastly_status)))
)

(@interface func (export "delete_wait")
(param $handle $kv_store_delete_handle)
(param $kv_error_out (@witx pointer $kv_error))
(result $err (expected (error $fastly_status)))
)

(@interface func (export "list")
(param $store $kv_store_handle)
(param $list_config_mask $kv_list_config_options)
(param $list_configuration (@witx pointer $kv_list_config))
(param $handle_out (@witx pointer $kv_store_list_handle))
(result $err (expected (error $fastly_status)))
)

(@interface func (export "list_wait")
(param $handle $kv_store_list_handle)
(param $body_handle_out (@witx pointer $body_handle))
(param $kv_error_out (@witx pointer $kv_error))
(result $err (expected (error $fastly_status)))
)
)

(module $fastly_secret_store
(@interface func (export "open")
(param $name string)
Expand Down
Loading

0 comments on commit 3fa4243

Please sign in to comment.