mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-02-25 18:55:38 -06:00
add writer to set_dht_value, allow multiple open_dht_record
This commit is contained in:
@@ -433,6 +433,7 @@ impl StorageManager {
|
||||
key: TypedKey,
|
||||
subkey: ValueSubkey,
|
||||
data: Vec<u8>,
|
||||
writer: Option<KeyPair>,
|
||||
) -> VeilidAPIResult<Option<ValueData>> {
|
||||
let mut inner = self.lock().await?;
|
||||
|
||||
@@ -451,6 +452,9 @@ impl StorageManager {
|
||||
)
|
||||
};
|
||||
|
||||
// Use the specified writer, or if not specified, the default writer when the record was opened
|
||||
let opt_writer = writer.or(opt_writer);
|
||||
|
||||
// If we don't have a writer then we can't write
|
||||
let Some(writer) = opt_writer else {
|
||||
apibail_generic!("value is not writable");
|
||||
|
||||
@@ -308,11 +308,6 @@ impl StorageManagerInner {
|
||||
writer: Option<KeyPair>,
|
||||
safety_selection: SafetySelection,
|
||||
) -> VeilidAPIResult<Option<DHTRecordDescriptor>> {
|
||||
// Ensure the record is closed
|
||||
if self.opened_records.contains_key(&key) {
|
||||
apibail_generic!("record is already open and should be closed first");
|
||||
}
|
||||
|
||||
// Get local record store
|
||||
let Some(local_record_store) = self.local_record_store.as_mut() else {
|
||||
apibail_not_initialized!();
|
||||
|
||||
@@ -42,10 +42,16 @@ impl OpenedRecord {
|
||||
pub fn writer(&self) -> Option<&KeyPair> {
|
||||
self.writer.as_ref()
|
||||
}
|
||||
// pub fn set_writer(&mut self, writer: Option<KeyPair>) {
|
||||
// self.writer = writer;
|
||||
// }
|
||||
|
||||
pub fn safety_selection(&self) -> SafetySelection {
|
||||
self.safety_selection
|
||||
}
|
||||
// pub fn set_safety_selection(&mut self, safety_selection: SafetySelection) {
|
||||
// self.safety_selection = safety_selection;
|
||||
// }
|
||||
|
||||
pub fn set_active_watch(&mut self, active_watch: ActiveWatch) {
|
||||
self.active_watch = Some(active_watch);
|
||||
|
||||
@@ -114,7 +114,7 @@ pub async fn test_set_get_dht_value(api: VeilidAPI) {
|
||||
|
||||
let test_value = String::from("BLAH BLAH BLAH").as_bytes().to_vec();
|
||||
// convert string to byte array
|
||||
let set_dht_value_result = rc.set_dht_value(dht_key, 0, test_value.clone()).await;
|
||||
let set_dht_value_result = rc.set_dht_value(dht_key, 0, test_value.clone(), None).await;
|
||||
assert_eq!(set_dht_value_result.expect("should be Ok(None)"), None);
|
||||
|
||||
let get_dht_value_result_0_non_force = rc.get_dht_value(dht_key, 0, false).await;
|
||||
@@ -184,7 +184,7 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) {
|
||||
// 5. Read data from subkey 0 with force_refresh, check data
|
||||
// 6. Read data from subkey 1 with force_refresh, check data
|
||||
// 7. Overwrite value 1 twice, check that there's no errors
|
||||
let set_dht_test_value_1_result = rc.set_dht_value(key, 1, test_value_1.clone()).await;
|
||||
let set_dht_test_value_1_result = rc.set_dht_value(key, 1, test_value_1.clone(), None).await;
|
||||
assert!(set_dht_test_value_1_result.is_ok());
|
||||
|
||||
let get_dht_value_result_1_non_force = rc.get_dht_value(key, 1, false).await;
|
||||
@@ -202,7 +202,7 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) {
|
||||
None
|
||||
);
|
||||
|
||||
let set_dht_test_value_0_result = rc.set_dht_value(key, 0, test_data_2.clone()).await;
|
||||
let set_dht_test_value_0_result = rc.set_dht_value(key, 0, test_data_2.clone(), None).await;
|
||||
assert!(set_dht_test_value_0_result.is_ok());
|
||||
|
||||
let get_dht_value_result_0_force = rc.get_dht_value(key, 0, true).await;
|
||||
@@ -223,10 +223,10 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) {
|
||||
test_value_1
|
||||
);
|
||||
|
||||
let overwrite_value_1_result_1 = rc.set_dht_value(key, 1, test_value_1.clone()).await;
|
||||
let overwrite_value_1_result_1 = rc.set_dht_value(key, 1, test_value_1.clone(), None).await;
|
||||
assert!(overwrite_value_1_result_1.is_ok());
|
||||
|
||||
let overwrite_value_1_result_2 = rc.set_dht_value(key, 1, test_data_2.clone()).await;
|
||||
let overwrite_value_1_result_2 = rc.set_dht_value(key, 1, test_data_2.clone(), None).await;
|
||||
assert!(overwrite_value_1_result_2.is_ok());
|
||||
|
||||
// Now that we initialized some subkeys
|
||||
@@ -258,7 +258,7 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) {
|
||||
));
|
||||
|
||||
//Verify subkey 1 can be set before it is get but newer is available online
|
||||
let set_dht_test_value_1_result = rc.set_dht_value(key, 1, test_data_3.clone()).await;
|
||||
let set_dht_test_value_1_result = rc.set_dht_value(key, 1, test_data_3.clone(), None).await;
|
||||
assert!(set_dht_test_value_1_result.is_ok());
|
||||
let vdtemp = set_dht_test_value_1_result.unwrap().unwrap();
|
||||
assert_eq!(vdtemp.data(), test_data_2);
|
||||
@@ -266,7 +266,7 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) {
|
||||
assert_eq!(vdtemp.writer(), owner);
|
||||
|
||||
// Verify subkey 1 can be set a second time and it updates because seq is newer
|
||||
let set_dht_test_value_1_result = rc.set_dht_value(key, 1, test_data_3.clone()).await;
|
||||
let set_dht_test_value_1_result = rc.set_dht_value(key, 1, test_data_3.clone(), None).await;
|
||||
assert!(set_dht_test_value_1_result.is_ok());
|
||||
|
||||
// Verify the network got the subkey update with a refresh check
|
||||
@@ -308,11 +308,17 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) {
|
||||
));
|
||||
|
||||
// Verify subkey 1 can NOT be set because we have the wrong writer
|
||||
let set_dht_test_value_0_result = rc.set_dht_value(key, 1, test_value_1.clone()).await;
|
||||
let set_dht_test_value_0_result = rc.set_dht_value(key, 1, test_value_1.clone(), None).await;
|
||||
assert_err!(set_dht_test_value_0_result);
|
||||
|
||||
// Verify subkey 0 can NOT be set because we have the wrong writer
|
||||
let set_dht_test_value_0_result = rc.set_dht_value(key, 0, test_value_1.clone()).await;
|
||||
let set_dht_test_value_0_result = rc.set_dht_value(key, 0, test_value_1.clone(), None).await;
|
||||
assert_err!(set_dht_test_value_0_result);
|
||||
|
||||
// Verify subkey 0 can be set because we have overridden with the correct writer
|
||||
let set_dht_test_value_0_result = rc
|
||||
.set_dht_value(key, 0, test_value_1.clone(), Some(keypair))
|
||||
.await;
|
||||
assert_err!(set_dht_test_value_0_result);
|
||||
|
||||
rc.close_dht_record(key).await.unwrap();
|
||||
|
||||
@@ -1517,9 +1517,14 @@ impl VeilidAPI {
|
||||
let (key, rc) = get_opened_dht_record_context(&args, "debug_record_set", "key", 1)?;
|
||||
let subkey = get_debug_argument_at(&args, 2, "debug_record_set", "subkey", get_number)?;
|
||||
let data = get_debug_argument_at(&args, 3, "debug_record_set", "data", get_data)?;
|
||||
let writer =
|
||||
get_debug_argument_at(&args, 4, "debug_record_set", "writer", get_keypair).ok();
|
||||
|
||||
// Do a record set
|
||||
let value = match rc.set_dht_value(key, subkey as ValueSubkey, data).await {
|
||||
let value = match rc
|
||||
.set_dht_value(key, subkey as ValueSubkey, data, writer)
|
||||
.await
|
||||
{
|
||||
Err(e) => {
|
||||
return Ok(format!("Can't set DHT value: {}", e));
|
||||
}
|
||||
|
||||
@@ -323,13 +323,18 @@ impl JsonRequestProcessor {
|
||||
.await,
|
||||
),
|
||||
},
|
||||
RoutingContextRequestOp::SetDhtValue { key, subkey, data } => {
|
||||
RoutingContextResponseOp::SetDhtValue {
|
||||
result: to_json_api_result(
|
||||
routing_context.set_dht_value(key, subkey, data).await,
|
||||
),
|
||||
}
|
||||
}
|
||||
RoutingContextRequestOp::SetDhtValue {
|
||||
key,
|
||||
subkey,
|
||||
data,
|
||||
writer,
|
||||
} => RoutingContextResponseOp::SetDhtValue {
|
||||
result: to_json_api_result(
|
||||
routing_context
|
||||
.set_dht_value(key, subkey, data, writer)
|
||||
.await,
|
||||
),
|
||||
},
|
||||
RoutingContextRequestOp::WatchDhtValues {
|
||||
key,
|
||||
subkeys,
|
||||
|
||||
@@ -70,6 +70,8 @@ pub enum RoutingContextRequestOp {
|
||||
#[serde(with = "as_human_base64")]
|
||||
#[schemars(with = "String")]
|
||||
data: Vec<u8>,
|
||||
#[schemars(with = "Option<String>")]
|
||||
writer: Option<KeyPair>,
|
||||
},
|
||||
WatchDhtValues {
|
||||
#[schemars(with = "String")]
|
||||
|
||||
@@ -215,19 +215,24 @@ impl RoutingContext {
|
||||
|
||||
/// Opens a DHT record at a specific key
|
||||
///
|
||||
/// Associates a secret if one is provided to provide writer capability.
|
||||
/// Records may only be opened or created. To re-open with a different routing context, first close the value.
|
||||
/// Associates a 'default_writer' secret if one is provided to provide writer capability. The
|
||||
/// writer can be overridden if specified here via the set_dht_value writer.
|
||||
///
|
||||
/// Records may only be opened or created. If a record is re-opened it will use the new writer and routing context
|
||||
/// ignoring the settings of the last time it was opened. This allows one to open a record a second time
|
||||
/// without first closing it, which will keep the active 'watches' on the record but change the default writer or
|
||||
/// safety selection.
|
||||
///
|
||||
/// Returns the DHT record descriptor for the opened record if successful
|
||||
pub async fn open_dht_record(
|
||||
&self,
|
||||
key: TypedKey,
|
||||
writer: Option<KeyPair>,
|
||||
default_writer: Option<KeyPair>,
|
||||
) -> VeilidAPIResult<DHTRecordDescriptor> {
|
||||
Crypto::validate_crypto_kind(key.kind)?;
|
||||
let storage_manager = self.api.storage_manager()?;
|
||||
storage_manager
|
||||
.open_record(key, writer, self.unlocked_inner.safety_selection)
|
||||
.open_record(key, default_writer, self.unlocked_inner.safety_selection)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -269,6 +274,9 @@ impl RoutingContext {
|
||||
}
|
||||
|
||||
/// Pushes a changed subkey value to the network
|
||||
/// The DHT record must first by opened via open_dht_record or create_dht_record.
|
||||
///
|
||||
/// The writer, if specified, will override the 'default_writer' specified when the record is opened.
|
||||
///
|
||||
/// Returns `None` if the value was successfully put
|
||||
/// Returns `Some(data)` if the value put was older than the one available on the network
|
||||
@@ -277,10 +285,11 @@ impl RoutingContext {
|
||||
key: TypedKey,
|
||||
subkey: ValueSubkey,
|
||||
data: Vec<u8>,
|
||||
writer: Option<KeyPair>,
|
||||
) -> VeilidAPIResult<Option<ValueData>> {
|
||||
Crypto::validate_crypto_kind(key.kind)?;
|
||||
let storage_manager = self.api.storage_manager()?;
|
||||
storage_manager.set_value(key, subkey, data).await
|
||||
storage_manager.set_value(key, subkey, data, writer).await
|
||||
}
|
||||
|
||||
/// Add a watch to a DHT value that informs the user via an VeilidUpdate::ValueChange callback when the record has subkeys change.
|
||||
|
||||
Reference in New Issue
Block a user