/// A keyvalue interface that provides eventually consistent batch operations.
///
/// A batch operation is an operation that operates on multiple keys at once.
///
/// Batch operations are useful for reducing network round-trip time. For example,
/// if you want to get the values associated with 100 keys, you can either do 100 get
/// operations or you can do 1 batch get operation. The batch operation is
/// faster because it only needs to make 1 network call instead of 100.
///
/// A batch operation does not guarantee atomicity, meaning that if the batch
/// operation fails, some of the keys may have been modified and some may not.
/// Transactional operations are being worked on and will be added in the future to
/// provide atomicity.
///
/// Data consistency in a key value store refers to the gaurantee that once a
/// write operation completes, all subsequent read operations will return the
/// value that was written.
///
/// The level of consistency in batch operations is **eventual consistency**, the same
/// with the readwrite interface. This interface does not guarantee strong consistency,
/// meaning that if a write operation completes, subsequent read operations may not return
/// the value that was written.
interface eventual-batch {
/// A keyvalue interface that provides batch get operations.
use types.{bucket, error, key, incoming-value, outgoing-value};
/// Get the values associated with the keys in the bucket. It returns a list of
/// incoming-value that can be consumed to get the value associated with the key.
///
/// If any of the keys do not exist in the bucket, it returns a `none` value for
/// that key in the list.
///
/// Note that the key-value pairs are guaranteed to be returned in the same order
///
/// MAY show an out-of-date value if there are concurrent writes to the bucket.
///
/// If any other error occurs, it returns an `Err(error)`.
get-many: func(bucket: borrow<bucket>, keys: list<key>) -> result<list<option<incoming-value>>, error>;
/// Get all the keys in the bucket. It returns a list of keys.
///
/// Note that the keys are not guaranteed to be returned in any particular order.
///
/// If the bucket is empty, it returns an empty list.
///
/// MAY show an out-of-date list of keys if there are concurrent writes to the bucket.
///
/// If any error occurs, it returns an `Err(error)`.
keys: func(bucket: borrow<bucket>) -> result<list<key>, error>;
/// Set the values associated with the keys in the bucket. If the key already
/// exists in the bucket, it overwrites the value.
///
/// Note that the key-value pairs are not guaranteed to be set in the order
/// they are provided.
///
/// If any of the keys do not exist in the bucket, it creates a new key-value pair.
///
/// If any other error occurs, it returns an `Err(error)`. When an error occurs, it
/// does not rollback the key-value pairs that were already set. Thus, this batch operation
/// does not guarantee atomicity, implying that some key-value pairs could be
/// set while others might fail.
///
/// Other concurrent operations may also be able to see the partial results.
set-many: func(bucket: borrow<bucket>, key-values: list<tuple<key, borrow<outgoing-value>>>) -> result<_, error>;
/// Delete the key-value pairs associated with the keys in the bucket.
///
/// Note that the key-value pairs are not guaranteed to be deleted in the order
/// they are provided.
///
/// If any of the keys do not exist in the bucket, it skips the key.
///
/// If any other error occurs, it returns an `Err(error)`. When an error occurs, it
/// does not rollback the key-value pairs that were already deleted. Thus, this batch operation
/// does not guarantee atomicity, implying that some key-value pairs could be
/// deleted while others might fail.
///
/// Other concurrent operations may also be able to see the partial results.
delete-many: func(bucket: borrow<bucket>, keys: list<key>) -> result<_, error>;
}