replace Option CRDT by explicit CancelingOption and MergingOption types

This commit is contained in:
Alex Auvolat
2026-05-04 19:51:35 +02:00
parent eb37a3e11a
commit bf0a24ea69
20 changed files with 237 additions and 133 deletions
+4 -4
View File
@@ -244,8 +244,8 @@ fn admin_token_info_results(token: &AdminApiToken, now: u64) -> GetAdminTokenInf
.expect("invalid timestamp stored in db"),
),
name: params.name.get().to_string(),
expiration: params.expiration.get().map(|x| {
DateTime::from_timestamp_millis(x as i64).expect("invalid timestamp stored in db")
expiration: params.expiration.get().inner().map(|x| {
DateTime::from_timestamp_millis(*x as i64).expect("invalid timestamp stored in db")
}),
expired: params.is_expired(now),
scope: params.scope.get().0.clone(),
@@ -279,10 +279,10 @@ fn apply_token_updates(
if let Some(expiration) = updates.expiration {
params
.expiration
.update(Some(expiration.timestamp_millis() as u64));
.update(Some(expiration.timestamp_millis() as u64).into());
}
if updates.never_expires {
params.expiration.update(None);
params.expiration.update(None.into());
}
if let Some(scope) = updates.scope {
params.scope.update(AdminApiTokenScope(scope));
+23 -20
View File
@@ -90,7 +90,7 @@ impl RequestHandler for GetBucketInfoRequest {
.bucket_alias_table
.get(&EmptyKey, &ga)
.await?
.and_then(|x| *x.state.get())
.and_then(|x| x.state.get().into_inner())
.ok_or_else(|| HelperError::NoSuchBucket(ga.to_string()))?,
(None, None, Some(search)) => {
let helper = garage.bucket_helper();
@@ -168,7 +168,7 @@ impl RequestHandler for CreateBucketRequest {
}
if let Some(alias) = garage.bucket_alias_table.get(&EmptyKey, ga).await? {
if alias.state.get().is_some() {
if alias.state.get().inner().is_some() {
return Err(CommonError::BucketAlreadyExists.into());
}
}
@@ -297,7 +297,7 @@ impl RequestHandler for UpdateBucketRequest {
let redirect_all = state
.website_config
.get()
.as_ref()
.inner()
.and_then(|wc| wc.redirect_all.clone());
let routing_rules = if let Some(rr) = wa.routing_rules {
@@ -311,26 +311,29 @@ impl RequestHandler for UpdateBucketRequest {
state
.website_config
.get()
.as_ref()
.inner()
.map(|wc| wc.routing_rules.clone())
.unwrap_or_default()
};
state.website_config.update(Some(WebsiteConfig {
index_document: wa.index_document.ok_or_bad_request(
"Please specify indexDocument when enabling website access.",
)?,
error_document: wa.error_document,
redirect_all,
routing_rules,
}));
state.website_config.update(
Some(WebsiteConfig {
index_document: wa.index_document.ok_or_bad_request(
"Please specify indexDocument when enabling website access.",
)?,
error_document: wa.error_document,
redirect_all,
routing_rules,
})
.into(),
);
} else {
if wa.index_document.is_some() || wa.error_document.is_some() {
return Err(Error::bad_request(
"Cannot specify indexDocument or errorDocument when disabling website access.",
));
}
state.website_config.update(None);
state.website_config.update(None.into());
}
}
@@ -353,7 +356,7 @@ impl RequestHandler for UpdateBucketRequest {
Some(cc.into_garage_cors_config()?)
};
state.cors_config.update(cors_config);
state.cors_config.update(cors_config.into());
}
if let Some(lr) = self.body.lifecycle_rules {
@@ -370,7 +373,7 @@ impl RequestHandler for UpdateBucketRequest {
)
};
state.lifecycle_config.update(lifecycle_config);
state.lifecycle_config.update(lifecycle_config.into());
}
garage.bucket_table.insert(&bucket).await?;
@@ -739,8 +742,8 @@ async fn bucket_info_results(
.filter(|(_, _, a)| *a)
.map(|(n, _, _)| n.to_string())
.collect::<Vec<_>>(),
website_access: state.website_config.get().is_some(),
website_config: state.website_config.get().clone().map(|wsc| {
website_access: state.website_config.get().inner().is_some(),
website_config: state.website_config.get().inner().cloned().map(|wsc| {
GetBucketInfoWebsiteResponse {
index_document: wsc.index_document,
error_document: wsc.error_document,
@@ -752,13 +755,13 @@ async fn bucket_info_results(
),
}
}),
cors_rules: state.cors_config.get().as_ref().map(|rules| {
cors_rules: state.cors_config.get().inner().map(|rules| {
rules
.iter()
.map(xml::cors::CorsRule::from_garage_cors_rule)
.collect::<Vec<_>>()
}),
lifecycle_rules: state.lifecycle_config.get().as_ref().map(|lc| {
lifecycle_rules: state.lifecycle_config.get().inner().map(|lc| {
lc.iter()
.map(xml::lifecycle::LifecycleRule::from_garage_lifecycle_rule)
.collect::<Vec<_>>()
@@ -784,7 +787,7 @@ async fn bucket_info_results(
.local_aliases
.items()
.iter()
.filter(|(_, _, b)| *b == Some(bucket.id))
.filter(|(_, _, b)| b.into_inner() == Some(bucket.id))
.map(|(n, _, _)| n.to_string())
.collect::<Vec<_>>(),
})
+7 -7
View File
@@ -40,8 +40,8 @@ impl RequestHandler for ListKeysRequest {
DateTime::from_timestamp_millis(x as i64)
.expect("invalid timestamp stored in db")
}),
expiration: p.expiration.get().map(|x| {
DateTime::from_timestamp_millis(x as i64)
expiration: p.expiration.get().inner().map(|x| {
DateTime::from_timestamp_millis(*x as i64)
.expect("invalid timestamp stored in db")
}),
expired: p.is_expired(now),
@@ -201,7 +201,7 @@ async fn key_info_results(
.local_aliases
.items()
.iter()
.filter_map(|(_, _, v)| v.as_ref()),
.filter_map(|(_, _, v)| v.inner()),
) {
if !relevant_buckets.contains_key(id) {
if let Some(b) = garage.bucket_table.get(&EmptyKey, id).await? {
@@ -217,8 +217,8 @@ async fn key_info_results(
created: key_state.created.map(|x| {
DateTime::from_timestamp_millis(x as i64).expect("invalid timestamp stored in db")
}),
expiration: key_state.expiration.get().map(|x| {
DateTime::from_timestamp_millis(x as i64).expect("invalid timestamp stored in db")
expiration: key_state.expiration.get().inner().map(|x| {
DateTime::from_timestamp_millis(*x as i64).expect("invalid timestamp stored in db")
}),
expired: key_state.is_expired(now_msec()),
access_key_id: key.key_id.clone(),
@@ -283,10 +283,10 @@ fn apply_key_updates(key: &mut Key, updates: UpdateKeyRequestBody) -> Result<(),
if let Some(expiration) = updates.expiration {
key_state
.expiration
.update(Some(expiration.timestamp_millis() as u64));
.update(Some(expiration.timestamp_millis() as u64).into());
}
if updates.never_expires {
key_state.expiration.update(None);
key_state.expiration.update(None.into());
}
if let Some(allow) = updates.allow {
if allow.create_bucket {
+1 -1
View File
@@ -164,7 +164,7 @@ async fn check_domain(garage: &Arc<Garage>, domain: &str) -> Result<bool, Error>
}
let bucket_state = bucket.state.as_option().unwrap();
let bucket_website_config = bucket_state.website_config.get();
let bucket_website_config = bucket_state.website_config.get().inner();
match bucket_website_config {
Some(_v) => Ok(true),