Eliminar los snapshots de un blob de Windows Azure Storage

Si habéis tenido que trabajar alguna vez con los blobs de Windows Azure Storage, y más aún si habéis hecho uso de los snapshot, ya habréis tenido el placer de encontraros con un error como este:

Si bien teníamos una forma de eliminar un blob con todos sus snapshots

blob.Delete(new BlobRequestOptions()
{
    DeleteSnapshotsOption = DeleteSnapshotsOption.IncludeSnapshots
});

Cuando queríamos eliminar uno solo la cosa se complica 🙁

Hasta ahora para recuperar un snapshot la única solución era llamar al método GetBlobReference con la siguiente estructura:

blob.GetBlobReference("filename?snapshot=<DateTime>");

Además la fecha debía tener el siguiente formato: 2010-03-07T00%3A12%3A14.1496934Z 

La otra opción era dejar de lado el Storage Client y crear nuestra propia llamada REST con los parámetros oportunos.

En cualquiera de los dos casos no era una forma muy simplificada de llevar a cabo una acción tan sencilla como recuperar un snapshot hasta la versión 1.3 😀

A partir de ahora disponemos de una sobrecarga de CloudBlobClient.GetBlobReference (aunque yo lo habría puesto dentro de CloudBlobContainer o al menos poner la sobrecarga en ambos métodos GetBlobReference) a la cual podemos pasar como parámetros tanto la URI del blob como el DateTime del snapshot que queremos recuperar.

Un dato importante a tener en cuenta es que la fecha debe ser UTC y obviamente debe ser exacta a la almacenada. Digo esto por el incidente que tuve al intentar recuperar el DateTime desde un ActionLink de ASP.NET MVC:

<%: Html.ActionLink("Delete", "Delete", new { item.Uri, item.ContainerName, item.SnapShotTime})%>

Al hacer esto, lo que está ocurriendo es que realiza un ToString() del DateTime dejando fuera los milisegundos que tenía asociados el snapshotTime (gracias Bruno :D), por lo que la fecha exacta ya no coincide. En mi caso, en vez de permitir esta conversión, paso como parámetro directamente la propiedad Ticks la cual devuelve un long:

<%: Html.ActionLink("Delete", "Delete", new { item.Uri, item.ContainerName,
                          item.SnapShotTime.Ticks })%>

De esta manera mantengo la fecha exacta y sólo necesitamos realizar la conversión a DateTime UTC en el servidor:

public void DeleteBlob(string uri, string containerName, long snapShotTimeTicks)
{
    var container = GetContainer(containerName);
    CloudBlob blob;
    if (snapShotTimeTicks != 0)
    {
        var utcSnapshotTime = new DateTime(snapShotTimeTicks, DateTimeKind.Utc);
        blob = _blobClient.GetBlobReference(uri, utcSnapshotTime);
    }
    else
       blob = container.GetBlobReference(uri);
   blob.Delete();
}

Espero que sea de utilidad 🙂

¡Saludos!