diff --git a/src/DataBlobs/services/BlobStores.jl b/src/DataBlobs/services/BlobStores.jl index 42eee96f..e1abc971 100644 --- a/src/DataBlobs/services/BlobStores.jl +++ b/src/DataBlobs/services/BlobStores.jl @@ -176,7 +176,10 @@ end function getBlob(store::FolderStore{T}, blobId::UUID) where {T} blobfilename = joinpath(store.folder, string(store.label), string(blobId)) - if isfile(blobfilename) + tombstonefile = blobfilename * ".deleted" + if isfile(tombstonefile) + throw(IdNotFoundError("Blob (deleted)", blobId)) + elseif isfile(blobfilename) open(blobfilename) do f return read(f) end @@ -198,24 +201,28 @@ function addBlob!(store::FolderStore{T}, blobId::UUID, data::T) where {T} end function updateBlob!(store::FolderStore{T}, blobId::UUID, data::T) where {T} - blobfilename = joinpath(store.folder, string(store.label), string(blobId)) - if !isfile(blobfilename) - @warn "Key '$blobId' doesn't exist." - else - open(blobfilename, "w") do f - return write(f, data) - end - return data - end + return error("updateBlob! is obsolete as blobsId=>Blob pairs are immutable.") end function deleteBlob!(store::FolderStore{T}, blobId::UUID) where {T} + # Tombstone pattern: instead of deleting the file, create a tombstone marker file blobfilename = joinpath(store.folder, string(store.label), string(blobId)) - if !isfile(blobfilename) + tombstonefile = blobfilename * ".deleted" + if isfile(blobfilename) + # Remove the actual blob file + rm(blobfilename) + # Create a tombstone marker + open(tombstonefile, "w") do f + return write(f, "deleted") + end + return 1 + elseif isfile(tombstonefile) + # Already deleted + return 0 + else + # Not found throw(IdNotFoundError("Blob", blobId)) end - rm(blobfilename) - return 1 end function hasBlob(store::FolderStore, blobId::UUID) @@ -225,7 +232,15 @@ end hasBlob(store::FolderStore, entry::Blobentry) = hasBlob(store, entry.blobId) -listBlobs(store::FolderStore) = readdir(store.folder) +function listBlobs(store::FolderStore) + folder = joinpath(store.folder, string(store.label)) + # Parse folder to only include UUIDs automatically excluding tombstone files this way. + blobIds = map(readdir(folder)) do filename + return tryparse(UUID, filename) + end + return filter(!isnothing, blobIds) +end + ##============================================================================== ## InMemoryBlobstore ##==============================================================================