Implement exact State Anchor mount and lease lifecycle

This commit is contained in:
ms2k 2026-07-15 16:54:03 +09:00
commit e6d6406c64

View file

@ -330,6 +330,32 @@ impl Catalog {
/// Returns an error if the artifact is absent or reclaiming, the lease exists, or the
/// transaction fails.
pub fn acquire_lease(&self, lease: &ArtifactLease) -> Result<(), CatalogError> {
self.acquire_lease_with(lease, None)
}
/// Inserts one lease only for an exactly matching available artifact row.
///
/// # Errors
/// Returns an error for artifact identity drift, absence, reclaim, lease conflict, or a
/// transaction failure.
pub fn acquire_lease_checked(
&self,
expected_artifact: &PreparedArtifact,
lease: &ArtifactLease,
) -> Result<(), CatalogError> {
if expected_artifact.prepared_artifact_id != lease.prepared_artifact_id {
return Err(CatalogError::OwnershipMismatch {
row: CatalogRow::PreparedArtifact,
});
}
self.acquire_lease_with(lease, Some(expected_artifact))
}
fn acquire_lease_with(
&self,
lease: &ArtifactLease,
expected_artifact: Option<&PreparedArtifact>,
) -> Result<(), CatalogError> {
self.write(|transaction| {
let artifact_key = artifact_key(lease.prepared_artifact_id);
let artifacts = transaction
@ -337,6 +363,11 @@ impl Catalog {
.map_err(CatalogError::redb)?;
let artifact: PreparedArtifact =
require_row(&artifacts, &artifact_key, CatalogRow::PreparedArtifact)?;
if expected_artifact.is_some_and(|expected| *expected != artifact) {
return Err(CatalogError::OwnershipMismatch {
row: CatalogRow::PreparedArtifact,
});
}
if artifact.state != ArtifactState::Available {
return Err(CatalogError::ArtifactUnavailable);
}
@ -359,7 +390,21 @@ impl Catalog {
///
/// Returns an error when the exact row is absent, forged, or the transaction fails.
pub fn release_lease(&self, expected: &ArtifactLease) -> Result<(), CatalogError> {
self.release_lease_checked(expected, || Ok(()))
}
/// Removes one exact lease only after caller-owned Domain and mount evidence is rechecked
/// while the catalog lock is held.
///
/// # Errors
/// Returns the evidence refusal or any exact-row and transaction failure without removal.
pub fn release_lease_checked(
&self,
expected: &ArtifactLease,
verify_release: impl FnOnce() -> Result<(), CatalogError>,
) -> Result<(), CatalogError> {
self.write(|transaction| {
verify_release()?;
let key = lease_key(expected);
let mut table = transaction.open_table(LEASES).map_err(CatalogError::redb)?;
require_exact(&table, &key, expected, CatalogRow::ArtifactLease)?;