4 Stimmen

Transaktionale CloudBlobs

Ich verwende SQL Azure für den Blob-Metadatenspeicher und Azure Blob Storage für die eigentlichen Blobs. Die Erstellung/Löschung von Blobs wird durch die Aufnahme dieser Vorgänge in das umgebende TransactionScope implementiert. Alles funktioniert so weit gut, aber ich frage mich, ob jemand Optimierungen für die Delete-Operation (siehe Quellcode unten) empfehlen kann, die die Anforderung zum Herunterladen der Blob-Inhalte, um Rollback loswerden könnte.

public class CloudBlobDeletionEnlistment : CloudBlobBaseEnlistment,
  IEnlistmentNotification,
  IDisposable
{
  public CloudBlobDeletionEnlistment(Guid ownerId, string blobId, CloudBlobContainer container, Logger logger, IUserUploadActivity currentUploadActivity)
  {
    ctx = new Context { OwnerId = ownerId, BlobId = blobId, Container = container, Logger = logger, CurrentUploadActivity = currentUploadActivity };
  }

  public ~CloudBlobDeletionEnlistment()
  {
    Dispose(false);
  }

  public class Context
  {
    public Guid OwnerId;
    public string BlobId;
    public string ContentFileName;
    public string MimeType;
    public bool IsCompressed;
    public CloudBlobContainer Container;
    public Logger Logger;
    public IUserUploadActivity CurrentUploadActivity;
  }

  private readonly Context ctx;
  private CloudBlob blob;

  public void Prepare(PreparingEnlistment preparingEnlistment)
  {
    blob = ctx.Container.GetBlobReference(ctx.BlobId);

    // save backup information
    ctx.ContentFileName = Path.GetTempFileName();
    blob.DownloadToFile(ctx.ContentFileName);
    blob.FetchAttributes();
    ctx.MimeType = blob.Metadata[Constants.BlobMetaAttributeContentType];
    ctx.IsCompressed = bool.Parse(blob.Metadata[Constants.BlobMetaAttributeCompressed]);

    // delete it
    blob.DeleteIfExists();

    // done
    preparingEnlistment.Prepared();
  }

  public void Commit(Enlistment enlistment)
  {
    Cleanup();

    // done
    enlistment.Done();
  }

  public void Rollback(Enlistment enlistment)
  {
    if (blob != null)
    {
      try
      {
        blob.UploadFile(ctx.ContentFileName);
        blob.Metadata[Constants.BlobMetaAttributeContentType] = ctx.MimeType;
        blob.Metadata[Constants.BlobMetaAttributeCompressed] = ctx.IsCompressed.ToString();
        blob.SetMetadata();
      }

      finally
      {
        Cleanup();
      }
    }

    else Cleanup();

    // done
    enlistment.Done();
  }

  public void InDoubt(Enlistment enlistment)
  {
    Cleanup();

    enlistment.Done();
  }

  void Cleanup()
  {
    // delete the temporary file holding the blob content
    if (!string.IsNullOrEmpty(ctx.ContentFileName) && File.Exists(ctx.ContentFileName))
    {
      File.Delete(ctx.ContentFileName);
      ctx.ContentFileName = null;
    }
  }

  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }

  protected virtual void Dispose(bool disposing)
  {
    if (disposing)
    {
      // free managed resources
    }

    // free native resources if there are any.
    Cleanup();
  }
  #endregion
}

1voto

Stuart Punkte 66386

Dies scheint mir kein sicherer Rollback-Mechanismus zu sein - der Upload könnte fehlschlagen, und wenn das passiert, wäre die Datenkonsistenz nicht mehr gegeben.

Wie wäre es, wenn Sie Ihre Blobs löschen, indem Sie ihre Namen in eine ToBeDeleted Tabelle in der Datenbank - und dann richten Sie einen regelmäßigen Job ein, der diese Blobs von Zeit zu Zeit löscht?

0voto

sebastus Punkte 350

Für mich sieht es so aus, als wollten Sie einen Blob und Metadaten in einem einzigen Transaktionskontext erstellen. Das ist nicht möglich. Ihre Programmlogik muss "die Transaktion sein".

Das Gleiche gilt für die Löschlogik.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X