[Resolved] Windows Azure Storage Known Issues 2013/11

Windows Azure Storage Known Issues 2013/11の既知の問題が解決されたとアナウンスがありました。Windows Azure Storage Known Issues (November 2013) [Resolved]どんな感じになったのかを確認しました。

引用

更新 [2013/12/10] : このBlog に記述されている問題 [1] は、service と client library の更新で解決されました。issue 2 の client table の件は、 2.1.0.4 [2]3.x [3] の client library の releases で解決されています。

matuyama by Takekazu Omi, on Flickr

問題点の確認

問題点は下記の3つが有りました。「3」は、既に、Storage Client 2.1.0.4 以降での Cast問題の修正で、Client Library 2.1.0.4、3.xで修正確認ができているので、ここでは1と2を確認します。

  1. SASとコンテナの前の// 問題
  2. TableのDataServiceContext.ResolveName 指定 問題
  3. Table Query での Cast 問題

SASとコンテナの前の “//” 問題

下記のようなプログラムで確認しました。Signitureの生成結果を確認しやすいように、2013/12/01から一年有効なREADのSASにしています。Storage Client 2.1.0.4 では、2012-02-12 versionが使われて、コンテナの前が"//"になっていても動きましたが、3.0.1だと、2013-08-15 versionが使われ、400 のエラーで弾かれるという結果になりました。もともと、"//"と書いたら"/"と解釈されるというのはあまりイケてない動きなので、古いバージョンのみ互換性を持つように変更して新しいものでは動作変更ということにしたのは妥当な落とし所かと思います。Storage Versionによって動作が違うようです。

private static string GetSASUrl(CloudStorageAccount storageAccount, string containerName, string blobName)
{
    var blobClient = storageAccount.CreateCloudBlobClient();

    var container = blobClient.GetContainerReference(containerName);

    var blockBlob = container.GetBlockBlobReference(blobName);

    var startDate = DateTime.Parse("2013/12/01");
    var sas = blockBlob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
    {
        Permissions = SharedAccessBlobPermissions.Read,
        SharedAccessStartTime = startDate,
        SharedAccessExpiryTime = startDate.AddYears(1)
    });
    
    return blockBlob.Uri.ToString() + sas;
}

2.1.0.4での確認結果

Install-Package WindowsAzure.Storage -Version 2.1.0.4で2.1.0.4を入れます。何度も、違うバージョンのライブラリを入れ替えて使っていて、混乱したので念のためpackage.configの内容を併記します。

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.Data.Edm" version="5.2.0" targetFramework="net451" />
  <package id="Microsoft.Data.OData" version="5.2.0" targetFramework="net451" />
  <package id="Microsoft.WindowsAzure.ConfigurationManager" version="1.8.0.0" targetFramework="net451" />
  <package id="System.Spatial" version="5.2.0" targetFramework="net451" />
  <package id="WindowsAzure.Storage" version="2.1.0.4" targetFramework="net451" />
</packages>

生成されたURLで成功を確認

コンテナの前に、"/"を追加して確認、成功!

sv=2012-02-12になっていて、versionがわかります。

3.0.1での確認結果

Install-Package WindowsAzure.Storageで最新版、3.0.1で確認

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.Data.Edm" version="5.6.0" targetFramework="net451" />
  <package id="Microsoft.Data.OData" version="5.6.0" targetFramework="net451" />
  <package id="Microsoft.Data.Services.Client" version="5.6.0" targetFramework="net451" />
  <package id="Microsoft.WindowsAzure.ConfigurationManager" version="1.8.0.0" targetFramework="net451" />
  <package id="Newtonsoft.Json" version="5.0.8" targetFramework="net451" />
  <package id="System.Spatial" version="5.6.0" targetFramework="net451" />
  <package id="WindowsAzure.Storage" version="3.0.1.0" targetFramework="net451" />
</packages>

生成されたURLで成功を確認

コンテナの前に、"/"を追加。これは失敗します。

レスポンスを見ると下記のようになっていました。(XMLは整形してあります)

HTTP/1.1 400 The requested URI does not represent any resource on the server.
Content-Length: 434
Content-Type: application/xml
Server: Microsoft-HTTPAPI/2.0
x-ms-request-id: a9275897-8810-48b2-bcd5-d45af85f6f14
Date: Fri, 27 Dec 2013 12:34:46 GMT

<?xml version="1.0" encoding="utf-8"?>
<Error>
  <Code>InvalidUri</Code>
  <Message>
    The requested URI does not represent any resource on the server.
    RequestId:a9275897-8810-48b2-bcd5-d45af85f6f14
    Time:2013-12-27T12:34:46.6851586Z
  </Message>
  <UriPath>
  http://test.blob.core.windows.net//images/photo.jpg?sv=2013-08-15&amp;sr=b&amp;sig=[signiture]&amp;se=2014-11-30T15:00:00Z&amp;sp=r
  </UriPath>
</Error>

TableのDataServiceContext.ResolveName 指定 問題

同様に、下記のようなコードを使って、2.1.0.4と、3.0.1で確認しました。 2.1.0.4 では、動作しましたが 3.0.1 では動きませんでした。結果はSASと似ているのですが、service側では処理が成功しているのでちょっと違った感じを受けます。

private static void ResolveName(CloudStorageAccount storageAccount)
{
    var cloudTableClient = storageAccount.CreateCloudTableClient();

    var table = cloudTableClient.GetTableReference("sometable");
    table.CreateIfNotExists();

    var tableServiceContext = cloudTableClient.GetTableServiceContext();
    tableServiceContext.ResolveName = entityType => entityType.FullName;

    var entity = new SimpleEntity("somePK", "someRK2");
    tableServiceContext.AddObject("sometable", entity);
    tableServiceContext.SaveChanges();
}

2.1.0.4での確認結果

普通に動いて成功しました。リクエストを見ると、categoryの属性に、term="StorageIssue201311.SimpleEntity"と有りますが、正常に処理されてレスポンスが帰ってきているのがわかります。

参考までに、リクエストとレスポンスを貼っておきます

リクエスト

POST http://test.table.core.windows.net/sometable HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 2.0;NetFx
x-ms-date: Fri, 27 Dec 2013 13:30:17 GMT
Authorization: SharedKeyLite [signiture]
x-ms-version: 2012-02-12
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
Content-Type: application/atom+xml
Host: test.table.core.windows.net
Content-Length: 735

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <category scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" term="StorageIssue201311.SimpleEntity" />
  <title />
  <author>
    <name />
  </author>
  <updated>2013-12-27T13:30:17.8428287Z</updated>
  <id />
  <content type="application/xml">
    <m:properties>
      <d:PartitionKey>somePK</d:PartitionKey>
      <d:RowKey>someRK7</d:RowKey>
      <d:Timestamp m:type="Edm.DateTime">0001-01-01T00:00:00</d:Timestamp>
    </m:properties>
  </content>
</entry>

レスポンス

HTTP/1.1 201 Created
Cache-Control: no-cache
Transfer-Encoding: chunked
Content-Type: application/atom+xml;type=entry;charset=utf-8
ETag: W/"datetime'2013-12-27T13%3A30%3A08.6638521Z'"
Location: http://test.table.core.windows.net/sometable(PartitionKey='somePK',RowKey='someRK7')
Server: Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 765ae397-974c-4f3c-9d3a-d4e99bdcf9f5
x-ms-version: 2012-02-12
X-Content-Type-Options: nosniff
Date: Fri, 27 Dec 2013 13:30:08 GMT

3AE
<?xml version="1.0" encoding="utf-8"?><entry xml:base="http://test.table.core.windows.net/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/&quot;datetime'2013-12-27T13%3A30%3A08.6638521Z'&quot;"><id>http://test.table.core.windows.net/sometable(PartitionKey='somePK',RowKey='someRK7')</id><category term="test.sometable" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /><link rel="edit" title="sometable" href="sometable(PartitionKey='somePK',RowKey='someRK7')" /><title /><updated>2013-12-27T13:30:08Z</updated><author><name /></author><content type="application/xml"><m:properties><d:PartitionKey>somePK</d:PartitionKey><d:RowKey>someRK7</d:RowKey><d:Timestamp m:type="Edm.DateTime">2013-12-27T13:30:08.6638521Z</d:Timestamp></m:properties></content></entry>
0



3.0.1での確認結果

Install-Package WindowsAzure.Storageとして最新版、3.0.1で確認したところ、下記のようにエラーになりました。データ自体は、Tableに入っており正常終了していますが、レスポンスを読み込んでエンティティを更新するのに失敗しているようです。

ハンドルされていない例外: System.Data.Services.Client.DataServiceRequestException: この要求の処理中にエラーが発生しました。 ---> System.InvalidOperationException: メタデータ URI 'http://fooomiimg001.table.core.windows.net/$metadata#sometable/@Element' は 'fooomiimg001.sometable' という名前のエンティティ型を参照していますが、予期されたエンティティ型の名前は 'StorageIssue201311.SimpleEntity' で、'fooomiimg001.sometable' という名前のエンティティ型と互換性がありません。 ---> Microsoft.Data.OData.ODataException: メタデータ URI 'http://fooomiimg001.table.core.windows.net/$metadata#sometable/@Element' は 'fooomiimg001.sometable' という名前のエンティティ型を参照していますが、予期されたエンティティ型の名前は 'StorageIssue201311.SimpleEntity' で、'fooomiimg001.sometable' という名前のエンティティ型と互換性がありません。
   場所 Microsoft.Data.OData.ReaderValidationUtils.ValidateFeedOrEntryMetadataUri(ODataJsonLightMetadataUriParseResult metadataUriParseResult, Scope scope)
   場所 Microsoft.Data.OData.JsonLight.ODataJsonLightReader.ReadAtStartImplementationSynchronously(DuplicatePropertyNamesChecker duplicatePropertyNamesChecker)
   場所 Microsoft.Data.OData.JsonLight.ODataJsonLightReader.ReadAtStartImplementation()
   場所 Microsoft.Data.OData.ODataReaderCore.ReadImplementation()
   場所 Microsoft.Data.OData.ODataReaderCore.ReadSynchronously()
   場所 Microsoft.Data.OData.ODataReaderCore.InterceptException[T](Func`1 action)
   場所 Microsoft.Data.OData.ODataReaderCore.Read()
   場所 System.Data.Services.Client.Materialization.ODataReaderWrapper.Read()
   場所 System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.TryRead()
   --- 内部例外スタック トレースの終わり ---
   場所 System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.TryRead()
   場所 System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.TryStartReadFeedOrEntry()
   場所 System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.TryReadFeedOrEntry(Boolean lazy, ODataFeed& feed, MaterializerEntry& entry)
   場所 System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.Read()
   場所 System.Data.Services.Client.Materialization.ODataReaderEntityMaterializer.ParseSingleEntityPayload(IODataResponseMessage message, ResponseInfo responseInfo, Type expectedType)
   場所 System.Data.Services.Client.SaveResult.HandleOperationResponseData(IODataResponseMessage responseMsg, Stream responseStream)
   --- 内部例外スタック トレースの終わり ---
   場所 System.Data.Services.Client.SaveResult.HandleResponse()
   場所 System.Data.Services.Client.BaseSaveResult.EndRequest()
   場所 System.Data.Services.Client.DataServiceContext.SaveChanges(SaveChangesOptions options)
   場所 System.Data.Services.Client.DataServiceContext.SaveChanges()
   場所 StorageIssue201311.Program.ResolveName(CloudStorageAccount storageAccount) 場所 c:\Users\Takekazu\Documents\GitHub\sandbox\csharp\StorageIssue201311\StorageIssue201311\Program.cs:行 52
   場所 StorageIssue201311.Program.Main(String[] args) 場所 c:\Users\Takekazu\Documents\GitHub\sandbox\csharp\StorageIssue201311\StorageIssue201311\Program.cs:行 59







参考までに、リクエストとレスポンスを貼っておきます。これを見ると、x-ms-version: 2013-08-15 で、payloadは、Content-Type: application/json;odata=minimalmetadataになっていますが、Prefer: return-no-contentが指定されておらず、レスポンスのBodyにechoが帰ってきているのがわかります。

リクエスト

POST http://test.table.core.windows.net/sometable HTTP/1.1
DataServiceVersion: 3.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
Accept: application/json;odata=minimalmetadata
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services
x-ms-date: Fri, 27 Dec 2013 13:07:55 GMT
Authorization: SharedKeyLite [signiture]
x-ms-version: 2013-08-15
Content-Type: application/json;odata=minimalmetadata
Host: test.table.core.windows.net
Content-Length: 125

{"odata.type":"StorageIssue201311.SimpleEntity","PartitionKey":"somePK","RowKey":"someRK6","Timestamp":"0001-01-01T00:00:00"}

レスポンス

HTTP/1.1 201 Created
Cache-Control: no-cache
Transfer-Encoding: chunked
Content-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8
ETag: W/"datetime'2013-12-27T13%3A07%3A45.3753816Z'"
Location: http://test.table.core.windows.net/sometable(PartitionKey='somePK',RowKey='someRK6')
Server: Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: b1797f33-1888-487a-a0cb-0a454fca1356
x-ms-version: 2013-08-15
X-Content-Type-Options: nosniff
Date: Fri, 27 Dec 2013 13:07:45 GMT

B2
{"odata.metadata":"http://test.table.core.windows.net/$metadata#sometable/@Element","PartitionKey":"somePK","RowKey":"someRK6","Timestamp":"2013-12-27T13:07:45.3753816Z"}
0


まとめ

Windows Azure Storage Known Issues 2013/11で報告されている既知の Braking Change は、2.1.0.4 の修正と、サーバー側(service)の修正でFIXされました。ただし、SASとコンテナの前の “//” 問題は、2013-08-15 version では仕様となり、TableのDataServiceContext.ResolveName 指定 問題も、Storage Client 3.0.1 では、ResolveNameの指定をすると動作しません。 最新のライブラリを使う場合はコードを直して欲しいということだと思います。

2.1系のライブラリを使う場合は上記3点の問題がFIXされた 2.1.0.4 がお勧めです。3.x系は、幾つかのBraking Changeが含まれるので既存のコードは移行が必要ですが、2013-08-15 versionのパフォーマンス向上策がちゃんと活用できるのが大きな利点だと言えます。



[1]日本語訳Windows Azure ストレージの既知の問題
[2]gitbugのWindowsAzure/azure-sdk-for-netレポジトリのmasterには、Storage Clientのコードは既にありません。2.1.0.4を確認するには、tag:v2.1.0.4 Storageを見て下さい。
[3]3.x github