normalian blog

Let's talk about Microsoft Azure, ASP.NET and Java!

Windows Azure SDK for Node.js でテーブルストレージを利用する〜失敗編?〜

Windows Azure 上での Node.js 開発が非常に容易になったが、今回は Windows Azure SDK for Node.js の簡単な利用方法について更に紹介する。以前記述したエントリである Windows Azure の大幅更新 〜Node.js編〜 id:waritohutsu:20111213:1323798292 を事前に一読して頂けると幸いだ。
前回までの記事では、Node.js 単体の機能しか利用しておらず、 express や socket.io といった Node.js の著名ライブラリのほか、Windows Azure ストレージサービスを利用する Node.js ライブラリ等も利用していなかった。今回は、これらの機能を利用するための簡単なTIPSを紹介する。

Node Package Manager について

Node.js をご存じの方には今更説明するまでもないことだと思うが、Node.js には npm(Node Package Manager)と呼ばれるパッケージ管理機構が存在する。.NETに詳しい方には、「Node.js版のNuGet」と言えば理解が容易だろう。以下にコマンドの実行例を紹介するが、インストールするライブラリの依存関係も含めて解決してくれる便利な機能だ。
以前は Windows版の Node.js では利用できなかったが、最近の Node.js では npm が利用できるようになった。

npm を利用してWindows Azure アプリケーションをセットアップ

前回の記事で紹介した手順を参考にサービスを作成する。まず、Azureのサービスを作成し、Workerロールを追加する。Windows Azure SDK for .NETPowerShellコマンドは Windows Azure PowerShell for Node.js Cmdlet Reference を参照して欲しい。

PS C:\temp> New-AzureService AzureNodeBlog

Service has been created at C:\temp\AzureNodeBlog

PS C:\temp\AzureNodeBlog> Add-AzureNodeWorkerRole

Role has been created at C:\temp\AzureNodeBlog\WorkerRole1. For easy access to
Windows Azure Services from your application code, install Windows Azure client
 library for Node.js by running ‘npm install azure’.

次に、Workerロールのディレクトリに移動して必要なライブラリをインストールする。本来は azure と express だけで十分だが、stylus ejs node-uuidをインストールした理由は後で述べる。

PS C:\temp\AzureNodeBlog> cd .\WorkerRole1
PS C:\temp\AzureNodeBlog\WorkerRole1> npm install azure
azure@0.5.1 ./node_modules/azure
├── xmlbuilder@0.3.1
├── qs@0.4.1
├── mime@1.2.4
├── xml2js@0.1.13
├── log@1.2.0
└── sax@0.3.5
PS C:\temp\AzureNodeBlog\WorkerRole1> npm install express stylus ejs node-uuid
express@2.5.6 ./node_modules/express
├── mime@1.2.4
├── mkdirp@0.0.7
├── qs@0.4.1
└── connect@1.8.5
ejs@0.6.1 ./node_modules/ejs
node-uuid@1.3.3 ./node_modules/node-uuid
stylus@0.22.6 ./node_modules/stylus
├── growl@1.1.0
├── mkdirp@0.0.7
└── cssom@0.2.1

最後に、Windows Azure エミュレータでアプリケーションを起動する。ただし、この時点では npm でインストールしたライブラリは利用していない。

PS C:\temp\AzureNodeBlog\WorkerRole1> Start-AzureEmulator -launch


Creating local package...
Starting Emulator...
Role is running at tcp://127.0.0.1:81
Role is running at tcp://127.0.0.1:8
Started

テーブルストレージを利用したブログサンプルを利用する

npm install azure でインストールしたパッケージ内にサンプルが存在するためそちらを利用しよう。サンプルは「C:\temp\AzureNodeBlog\WorkerRole1\node_modules\azure\examples\blog」に配置されており、こちらのサンプルがstylus ejs node-uuidを利用するために先ほどの手順では同パッケージもインストールしていただいた。こちらのサンプルを「C:\temp\AzureNodeBlog\WorkerRole1」に上書きする。次に、同フォルダに存在する blog.js を開き、以下の様に編集する。

//var azure = require('./../../lib/azure');
var azure = require('azure');
var ServiceClient = azure.ServiceClient;
var TableQuery = azure.TableQuery;
var uuid = require('node-uuid');

var tableName = 'posts';
var partition = 'part1';

Blog = function () {
  this.tableClient = azure.createTableService(ServiceClient.DEVSTORE_STORAGE_ACCOUNT, ServiceClient.DEVSTORE_STORAGE_ACCESS_KEY, ServiceClient.DEVSTORE_TABLE_HOST);
};

(以下略)

上記の完了後、再度以下の手順でエミュレータを起動する。

PS C:\temp\AzureNodeBlog\WorkerRole1> Start-AzureEmulator -launch


Creating local package...
Starting Emulator...
Role is running at tcp://127.0.0.1:81
Role is running at tcp://127.0.0.1:8
Started

無事アプリケーションの実行が完了した場合、次の画面が表示されるはずだ。

しかし、ポストを投稿したところうまく反映されなかった。Compute Storageを確認したところ、テーブルそのものは作成されていたので、引き続き問題を解析したいと思う。

テーブルストレージの利用方法

今回はテーブルストレージを利用したブログサンプルであり、以下の様に .NET版ライブラリと大差ないインターフェースでストレージサービスを利用できる(はずだったが。。。)。以下は参考LVで書いたコードであるため、実際に動作検証をしてるわけではないので注意してほしい。

var ServiceClient = azure.ServiceClient;
var TableQuery = azure.TableQuery;
var uuid = require('node-uuid');

var tableName = 'posts';
var partition = 'part1';

Blog = function () {
  //開発ストレージの利用設定
  this.tableClient = azure.createTableService(ServiceClient.DEVSTORE_STORAGE_ACCOUNT, ServiceClient.DEVSTORE_STORAGE_ACCESS_KEY, ServiceClient.DEVSTORE_TABLE_HOST);
};

//全県検索
var tableQuery = TableQuery.select().from(tableName);
tableClient.queryEntities(tableQuery, callback);

//ID検索
tableClient.queryEntity(tableName, partition, id);

//エンティティを削除
var entity = { PartitionKey: partition, RowKey: id };
tableClient.deleteEntity(tableName, entity);

//エンティティの挿入
tableClient.insertEntity(tableName, { PartitionKey: partition, RowKey: uuid(), title: 'Post one', body: 'Body one', created_at: now });