C
C#2y ago
linqisnice

❔ how do i make blob and entity deletion atomic?

{
public async Task<IResult> Handle(DeleteImageCommand request, CancellationToken cancellationToken)
{
var photo = await _dbContext.ListingPhotos.FindAsync(request.Id);


if(photo is not null)
{
await DeleteBlob(photo.BlobName, containerName);
_dbContext.ListingPhotos.Remove(photo);
}

return Results.Ok();
}

private async Task DeleteBlob(string blobName, string containerName)
{
var containerClient = _blobServiceClient.GetBlobContainerClient(containerName);

if (!await containerClient.ExistsAsync())
throw new ApplicationException($"Unable to upload blobs to container {containerName} as the container does not exist.");


var blobClient = containerClient.GetBlobClient(blobName);
if (!await blobClient.ExistsAsync())
throw new ApplicationException($"Unable to delete blob {blobName} in container '{containerName}' as no blob with this name exists in this container");


var response = await blobClient.DeleteAsync();

if (response.Status != 200)
{
throw new ApplicationException($"Failed to delete blob {blobName} in container '{containerName}' with status code {response.Status}");
}
}
{
public async Task<IResult> Handle(DeleteImageCommand request, CancellationToken cancellationToken)
{
var photo = await _dbContext.ListingPhotos.FindAsync(request.Id);


if(photo is not null)
{
await DeleteBlob(photo.BlobName, containerName);
_dbContext.ListingPhotos.Remove(photo);
}

return Results.Ok();
}

private async Task DeleteBlob(string blobName, string containerName)
{
var containerClient = _blobServiceClient.GetBlobContainerClient(containerName);

if (!await containerClient.ExistsAsync())
throw new ApplicationException($"Unable to upload blobs to container {containerName} as the container does not exist.");


var blobClient = containerClient.GetBlobClient(blobName);
if (!await blobClient.ExistsAsync())
throw new ApplicationException($"Unable to delete blob {blobName} in container '{containerName}' as no blob with this name exists in this container");


var response = await blobClient.DeleteAsync();

if (response.Status != 200)
{
throw new ApplicationException($"Failed to delete blob {blobName} in container '{containerName}' with status code {response.Status}");
}
}
In this code, what if blob removal is successful but listingphotos.remove somehow fails? 1. Is it something to worry about? 2. Should I do retries? 3. Compensating transaction of some kind? if removal of the entity fails > restore the deleted blob?
11 Replies
Angius
Angius2y ago
Remove the entry from the database first, and remove the file from the blob storage only if that succeeded
linqisnice
linqisniceOP2y ago
Haha, that is almost hilariously simple and would solve my problem. lol @AngiusShould i retry the blob deletion then? maybe i dont want wasted space elsewhere maybe, match it against db records maybe a background task
Angius
Angius2y ago
I'd retry, like, once If that fails, just log it and handle it somehow else
linqisnice
linqisniceOP2y ago
gotcha, and by handle it somehow else maybe a regularly scheduled background task?
Angius
Angius2y ago
That could work, yeah Save all the orphaned files to some JSON file or a database table or something And run cleanup once a week or so You could even skip the retries then, rbh
linqisnice
linqisniceOP2y ago
yeah, sounds like a good approach. does the code look ok other than that?
Angius
Angius2y ago
LGTM at a glance
linqisnice
linqisniceOP2y ago
thanks, appreciate the help. actually suspected you would reply when i posted haha, you've replied on all my posts 😄 dfont know how u do it but man u put in the time and it's great
Angius
Angius2y ago
I simply browse #help regularly lol
linqisnice
linqisniceOP2y ago
yeah, uir doin the lords work man 😛 cheers
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server