quarta-feira, 30 de setembro de 2009

404 Resource Not Found For Segment acessando o Table Storage do Azure

Essa tem algo a ver com o acesso ao Azure ser baseado em REST (Representational State Transfer). Devo confessar minha ignorância, pois li um pouco sobre REST mas não entendi quase nada. Mas pelo que entendi, é uma forma de arquitetura para softwares distribuídos. Engraçado que foi criado baseado em uma análise da Internet como software, e parece criar uma teoria bastante complicada em cima de algo que já usamos e, de certa forma, já dominamos.

Bem, o négocio é o seguinte: fui procurar um item em uma tabela no Table Storage do Azure. Inicialmente, a impressão que dava é que o erro retornado - 404 Resource Not Found for Segment 'Nome da Tabela' - aparecia aleatoriamente. Depois vimos que ele aparecia quando a tabela na qual fazíamos a procura estava vazia. E na verdade, um comentário de Andrew Conrad, que participa do projeto de Linq To REST da Microsoft, indica que este erro aparece quando o item é procurado por sua chave e não é encontrado na lista. Isto porque, segundo REST, as aplicações distribuídas são compostas de clientes e servidores, e os servidores fornecem recursos aos clientes - como os arquivos de um servidor Web. Então, quando uma consulta REST procura um recurso específico - como p.e., uma consulta Linq em uma tabela no Table Storage do Azure, e este recurso não é encontrado, é retornado o erro "Resource Not Found" - como o erro 404 em HTTP.

Este erro parece obedecer à teoria do REST, mas realmente, quando você trabalha com algo chamado *Table* Storage, a primeira coisa que vem na cabeça é algo semelhante ao acesso a um BD, e não um acesso a um recurso REST. Então quando algo não é encontrado, a gente espera um resultset vazio, e não um erro. Pelo comentário do Andrew Conrad citado acima, eles já estão cientes desta, digamos, "peculiaridade" do Azure, e planejam fazer algo mais intuitivo na próxima versão.

Por enquanto a solução é envolver seu código em um Try/Catch nada elegante:
try
{
var elemento =
(for item in contextoAzure.MinhaTabela
where item.PartitionKey = '...' and item.RowKey = '...'
select item).FirstOrDefault();
}
catch (DataServiceQueryException erro)
{
if(erro.Response.StatusCode == 404)
// elemento não foi encontrado
}