mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-07 20:46:11 +00:00
fix(site-replication): persist source stamps and apply IAM items atomically (backlog#2291)
Review findings on rustfs#7195: the receive-side staleness gate compared a source `updatedAt` against a stamp the local write had put on the record, and the verdict, the write and the deletion mark were three separate steps. - IAM writes gain explicit-stamp variants (`set_policy_at`, `policy_db_set_at`, group and user `*_at`, `new_service_account_at`, `update_service_account_at`) so a replicated record carries its source time; local edits are unchanged. - `apply_iam_item` runs verdict, write and mark commit under the site-replication state transaction (distributed state-object lock), so a concurrent older grant and newer revoke are ordered on every node. - A replicated service account is created with its source status in one write (`NewServiceAccountOpts::status`), never enabled transiently. - Deletion marks are pruned by age (30 days) instead of by count. - Bucket-config deletes persist the source stamp (`delete_if_incarnation_at`). Regressions run through the real receiver: delayed in-order updates for every gated item type, concurrent grant/revoke, delete then stale re-create, disabled service-account create, delete stamping in ecstore, and mark retention.
This commit is contained in:
@@ -45,18 +45,33 @@ pub struct PolicyDoc {
|
||||
|
||||
impl PolicyDoc {
|
||||
pub fn new(policy: Policy) -> Self {
|
||||
Self::new_at(policy, OffsetDateTime::now_utc())
|
||||
}
|
||||
|
||||
/// [`Self::new`] with an explicit `UpdateDate` (and `CreateDate`).
|
||||
///
|
||||
/// A replicated document keeps the edit's source time: the receiver
|
||||
/// judges the next incoming revision against the stored stamp, so a
|
||||
/// local stamp would reject a newer source edit that was merely
|
||||
/// delivered later.
|
||||
pub fn new_at(policy: Policy, at: OffsetDateTime) -> Self {
|
||||
Self {
|
||||
version: 1,
|
||||
policy,
|
||||
create_date: Some(OffsetDateTime::now_utc()),
|
||||
update_date: Some(OffsetDateTime::now_utc()),
|
||||
create_date: Some(at),
|
||||
update_date: Some(at),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, policy: Policy) {
|
||||
self.update_at(policy, OffsetDateTime::now_utc());
|
||||
}
|
||||
|
||||
/// [`Self::update`] with an explicit `UpdateDate`; see [`Self::new_at`].
|
||||
pub fn update_at(&mut self, policy: Policy, at: OffsetDateTime) {
|
||||
self.version += 1;
|
||||
self.policy = policy;
|
||||
self.update_date = Some(OffsetDateTime::now_utc());
|
||||
self.update_date = Some(at);
|
||||
|
||||
if self.create_date.is_none() {
|
||||
self.create_date = self.update_date;
|
||||
|
||||
Reference in New Issue
Block a user