Windows Azure Storage Known Issues 2013/11

2013/11/29 以下の内容は正式な日本語訳が出ています Windows Azure ストレージの既知の問題
2013/11/30 Table Query での Cast 問題 が解決されたStorage Client Libraryがリリースされています。検証記事 Storage Client 2.1.0.4 以降での Cast問題の修正

cros, json 対応などのmajor releaseの準備に伴って実装が変更されているようです。それが原因でいくつかの意図しない問題が発生していることが報告されています。以下は Windows Azure Storage の BlogWindows Azure Storage Known Issues (November 2013)からの抜粋です。これらの問題が修正されプロダクションに公開され次第 Blog の記事は更新されるということです。

Windows Azure Blobs, Tables and Queue Shared Access Signature (SAS)のIssue

  • 下記のような、2012-02-12 バージョンのSASが、 HTTP Status Code 400 (Bad Request)になります。従来の実装だと、コンテナの前の“//”は、“/”に折りたたまれて処理されていましたが、現時点ではコンテナが無効である(null)として解釈されてしまいます。これは、修正される予定ですが、当面は“//”を送らないようにして下さい

http://myaccount.blob.core.windows.net//container/blob?sv=2012-02-12&si=sasid&sx=xxxx

Windows Azure TablesのIssue

下記の2つの既知のissueがあります。サービス側または当社のクライアント·ライブラリの一部としてhotfixを出す予定です。

  1. clients で、DataServiceContext.ResolveNameを定義し、<Account Name>.<Table Name>以外の型の名前を指定すると、CUD operation が 400 (Bad Request) を返します。これは、新しい実装では、ATOM の “Category” element の term 属性が、<Account Name>.<Table Name> と同じで無ければいけないのが原因です。以前のバージョン(実装)では、送信された型の名前は無視していました。これは再び無視するように修正される予定ですが、それまでの間は次の回避策を検討してください。ResolveName の設定は、Azure Tables では必要無いのでclient application のから外してください。そうすると OData の “category” element は送信されません。

下記は問題が発生するコードの例です。これを実行するとサーバー側で失敗します。

CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
TableServiceContext tableServiceContext = cloudTableClient.GetDataServiceContext();
tableServiceContext.ResolveName = delegate(Type entityType)
{
// This would cause class name to be sent as the value for term in the category element and service would return Bad Request.
return entityType.FullName;
};

SimpleEntity entity = new SimpleEntity("somePK", "someRK");
tableServiceContext.AddObject("sometable", entity);
tableServiceContext.SaveChanges();

この Issue の解決のためには client 側でtableServiceContext.ResolveNamedelegate の設定を外してください。

  1. service updateの一環として、サーバー側で使っている新しい .NET WCF Data Services library は、$filter query の 一部に empty “cast” があると 400 (Bad Request) で拒否します。古い .NET framework libraryではそうではありませんでした。これによって、Windows Azure Storage Client Library 2.1のIQueryable implementationに影響が出ます。.NET の DataServiceContext の挙動を、cast を送信しないようにクライアントライブラリを修正中です。これは、数週間以内に利用できるようになります( this should be available in the next couple of weeks )それまでの間次の回避策を検討してください。このクライアントライブラリの問題では、IEnumerable<T> で ITableEntityインターフェイスに制約するのでは無く、インスタンス化される型を明示的に使うことで回避できます。

下記は問題があるコードです

static IEnumerable<T> GetEntities<T>(CloudTable table)  where T : ITableEntity, new()
{
    IQueryable<T> query = table.CreateQuery<T>().Where(x => x.PartitionKey == "mypk");
    return query.ToList();
}

このように書くと 2.1 storage client library の IQueryable interface は、下記のUriに展開されて新しい service updateでは、400 (Bad Request) で拒否されます

http://myaccount.table.core.windows.net/invalidfiltertable?$filter=cast%28%27%27%29%2FPartitionKey%20eq%20%27mypk%27&timeout=90

コードを下記のように変更してquery の castを取り除いてください。そうすれば、cast operator は送信されません

IQueryable<SimpleEntity> query = table.CreateQuery<SimpleEntity>().Where(x => x.PartitionKey == "mypk");
return query.ToList();

Uri request は下記のようになり、service に受け付けられます

http://myaccount.table.core.windows.net/validfiltertable?$filter=PartitionKey%20eq%20%27mypk%27&timeout=90

We apologize for these issues and we are working on a hotfix to address them. (我々はこれらの問題について謝罪し、我々はそれらに対処するための修正プログラムに取り組んでいます)

感想、コメント等

  • 最後の Uriに cast operatorが出てしまって、それがあるとサーバーではねられて 400 (Bad Request) というのは嵌りそうです。回避策もなかなか厳しい気がします。
  • コンテナの前が//になってるとSASが効かないっていうのは、自前でUriを作成していると起きそうな気がします。要注意ですね。
  • ResolveName の件は、DataServiceContextにあって、TableServiceContextでは動作に関係しないものという混乱の原因になりがちなやつです。元々意味無かったはずなので、外せば良いと思います。