事务性 CloudBlob

发布于 2024-11-27 01:48:17 字数 2805 浏览 0 评论 0原文

我使用 SQL Azure 来存储 Blob 元数据,使用 Azure Blob 存储来存储实际的 Blob。 Blob 创建/删除是通过在环境 TransactionScope 中登记这些操作来实现的。到目前为止,一切工作正常,但我想知道是否有人可以建议对删除操作进行优化(请参阅下面的源代码),这可能会消除下载 blob 内容以进行回滚的要求。

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
}

I'm using SQL Azure for Blob Meta Data Storage and Azure Blob Storage for the actual blobs. Blob Creation/Deletion is implemented by enlisting those operation in the ambient TransactionScope. Everything works fine so far but I'm wondering if anyone can recommend optimizations to the Delete-Operation (see source code below) that might get-rid of the requirement to download the blob contents in order to rollback.

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
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

就此别过 2024-12-04 01:48:17

对我来说,这似乎不是一个安全的回滚机制 - 上传可能会失败,如果发生这种情况,那么您的数据一致性就会被破坏。

如果您通过将 Blob 的名称放入数据库中的 ToBeDeleted 表中来删除 Blob,然后您设置一些常规作业时不时地删除这些 Blob,会怎么样?

This doesn't seem like a safe rollback mechanism to me - the upload could fail and if that occurs then your data consistency would be broken.

What about if you delete your blobs by putting their names into a ToBeDeleted table in the database - and then you set up some regular job deletes these blobs from time to time?

静待花开 2024-12-04 01:48:17

在我看来,您想要创建一个 blob 并在单个事务上下文中创建元数据。这是不可能的。您的程序逻辑必须“是事务”。

这同样适用于删除逻辑。

It looks to me like you want to create a blob and create metadata in a single transaction context. This is not possible. Your program logic must "be the transaction".

The same applies to delete logic.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文