domingo, 10 de outubro de 2010

bulkload (Carga de dados) e consumo de CPU no GAE

Buenas!

Este post é só pra mostrar algumas estatísticas do GAE com relação ao processamento. Estou fazendo uns testes de carga pro datastore e já comecei a receber alguns erros... Mas calma! estes erros são plausíveis e explicáveis, não se preocupe... rs

Bom, seguinte... Imagine seu desktop bombando de threads de upload de dados... Não consegue? Seria algo assim:

Figura 1: Upload de dados

Pois é... Você já viu aí uma pancada de erros né? Mais especificamente o erro 503 do protocolo http. Você então, como administrador da aplicação, vai checar o dashboard pra ver que WTF tá acontecendo:

Figura 2: Dashboard da aplicação.


É, cpu bombando né? Neste ponto tenho 3 assuntos a abordar:

  1. Bulkload de dados. Nada mais é que carregar seus dados para sua aplicação no cloud do google. É justamente o que a figura 1 demonstra.
  2. Gerenciamento da aplicação. Reparem nos ícones de warning na figura 2. Porque eles estão ali?
  3. Consumo de CPU. Porque a minha aplicação, que está em pleno desenvolvimento, consumiu esta quantidade toda de CPU em menos de 2 horas?
Nos próximos posts pretendo explicar cada um dos itens acima. Stay tuned! :)

Até!

terça-feira, 5 de outubro de 2010

Utilizando o operador like em consultas ao datastore do GAE

É uma tendência natural e inevitável quando migramos de tecnologia fazer comparações entre elas. Recentemente comecei um projeto utilizando a estrutura Cloud do Google e, consequentemente, utilizando um banco NoSQL, o BigTable.

Em projetos normais costumamos utilizar um banco de dados relacional, onde estamos acostumados a utilizar comandos SQL para efetuar consultas no nosso banco. Porém, quando migramos para uma plataforma cloud e bancos NoSQL, não temos mais uma base relacional e consequentemente nossa estrutura de armazenamento muda um pouco (ou muito!). Não vou me aprofundar neste assunto por haver muitas discussões interessantes pela internet.

Em bancos NoSQL temos sérias restrições a consultas que estamos acostumados a fazer em bancos relacionais. Agrupamentos como counts e sums, operadores like e alguns joins são bem restritos. Neste post irei focar no uso do operador like para consultas a campos String.

Bem, chega de papo e vamos ao que interessa. Nestes exemplos, farei analogias entre os bancos relacionais para facilitar o entendimento. Utilizarei também como framework de persistência da minha aplicação o Objectify (existem outros frameworks focados em bancos NoSQL, como o twig e o SimpleDS, mas ainda não os testei). Antes que perguntem, não, não é possível utilizar Hibernate. Além da diferença conceitual pelo fato do Hibernate ser um framework ORM, o próprio google disponibizou a sua lista de compatibilidade. Vale ressaltar que o GAE suporta JPA, portanto é possível fazer "algumas coisas" bem parecidas de como estamos acostumados. Entretanto já ouvi, li e concordo que o conceito destes bancos é diferente, portanto é um "workaround" utilizar JPA ou JDO com estes bancos, visto que algumas funcionalidades não são suportadas.

Na prática, vamos supor que você tem um requisito no qual seu cliente quer consultar uma cidade pelo nome. Precisamos então da nossa entidade Cidade:











Instantâneamente na sua cabeça lógica de desenvolvedor aparece a sentença:

"select nome, uf from Cidade where nome like 'paulo%'"

Certo? Num banco relacional sim. Porém, o foco aqui é o nosso BigTable. Análogamente utilizando o Objectify faríamos:









Ótimo. Porém o requisito diz que devemos buscar as cidades não importando a ordem das palavras. Ou seja, se o usuário digitar "paulo", a lista deve conter Paulo Jacinto, Paulo Afonso, São Paulo, Monsenhor Paulo, etc. Fácil. É só colocar mais um %, não é? Ficaria:

"select nome, uf from Cidade where nome like '%paulo%'"

#ihcomplicou. Uma das restrições no uso de bancos NoSQL que citei no início é justamente esta. A solução? Quem sabe indexar os termos de busca da sua entidade? Parece uma boa...

Precisamos então adicionar um novo atributo na nossa entidade Cidade. Criei então um List do tipo string chamado indexedName, como segue:



Agora, precisamos preencher esta lista de termos com os termos relevantes à pesquisa. No meu caso, criei um "IndexBuilder" responsável por elencar os termos pesquisáveis. Esta classe tem a função de "limpar" a string que estou passando à ela, removendo acentos, pontos, vírgulas e passando tudo pra lowercase (selects com lowercase e uppercase também não são possíveis no BigTable). Ele me retorna um List contendo cada palavra quebrada pelo " " (espaço, via split) entre uma palavra e outra do termo. Caso necessário, é perfeitamente possível componentizar este "builder" para tipos de indexadores específicos para o seu domínio. Basta interfacear este cara e invocá-lo por um container IoC ou uma factory qualquer. Use a imaginação!

Ótimo. Já temos o atributo de indexação de pesquisa e também o componente responsável por lidar com estes termos. Agora precisamos de algo que ligue os pontos. Para isto, o Objectify provê anotações para métodos das nossas entidades em 2 momentos. @PostLoad (logo após recuperar o objeto do datastore) e @PrePersist (antes de gravar no datastore). Utilizei a anotação @PrePersist no método onSave que irá chamar o nosso componente indexador e preencher o atributo indexedName da nossa entidade. Falei também para o Objectify não indexar os campos nome e uf (uma vez que não vou pesquisar por eles), e explicitamente disse que o indexedName é indexado (por padrão, todos os campos são indexados):



Feito isto, basta agora buscar a cidade pelo nosso atributo indexedName, ao invés do atributo nome. Algo como:



Desta forma o usuário terá a experiência de estar utilizando uma busca "full text", ou seja, o termo digitado será utilizado independente de maiúsculas, minúsculas, acento e formatação (de acordo com o seu componente de indexação). Caso o usuário busque por "paulo", o sistema retornará São Paulo, São Paulo da Fartura, Pedro Paulo Diniz, Padaria do Paulo, Seu Paulo da Esquina, etc...


O resultado é algo como: 




Até! :)


referências: http://groups.google.com/group/objectify-appengine/browse_thread/thread/be46b724c5176f61

sábado, 28 de agosto de 2010

Habilitando as funções de navegação entre músicas no seu Iphone/Ipod via bluetooth

Recentemente troquei meu carro por um carro que vem de fábrica o som com bluetooth e comandos no volante. Bacana! Como qualquer louco que adora tecnologia, minha primeira idéia foi conectar o meu iphone 3GS no bluetooth do carro e poder desfrutar do acervo de 16gb de músicas.

Foi lindo. As funções de discagem por voz funcionam perfeitamente simplesmente apertando um botão no volante. E a rediscagem ou atender uma ligação então? perfeito! Mais um clique no volante e mudo o source do som pra tocar as músicas no iphone. Dou um play, pause, mudo o volume, seleciono um shuffle no meu acervo e quando vou trocar para a próxima música no Iphone, nada acontece. Que? como assim?

É isto mesmo. Fui direto no manual do som do carro pensando que o rádio certamente teria implementado nas coxas o protocolo de comunicação entre dispositivos bluetooth. Para minha surpresa, o manual dizia que implementava religiosamente os protocolos definidos num padrão lá que eu não lembro o nome. Weird, huh?

Lembrei então que esta função também não funcionava num fone estéreo bluetooth q eu tinha, um Motorola S9 (que por sinal morreu repentinamente... :( ). Então, o plin na mente! Este iphone tá brincando comigo.

Google na veia, descobri que existe uma especificação chamada AVRCP que define os padrões para aparelhos que querem disponibilizar funções de navegação de áudio entre dispositivos. Que mancada hein apple? O melhor e mais vendido player do mercado não implementa esta especificação? Lembrei-me de um nokia tosquíssimo que tinha há um bom tempo atrás que funcionava perfeitamente com um fone estéreo bluetooth véio também...

Ótimo. Problema descoberto. E ai Xenevréu? como eu resolvo isto? Simples! Você precisa de um cara instalado no Iphone chamado Music Controls! Para isto, você precisa:

  1. Que seu Iphone esteja Jailbroken. O que é isto? google it meu amigo :)
  2. US$ 4,99 disponível via paypal.
  3. Entrar no cydia - search - digitar Music controls e instalar o menino.
  4. Após instalado, entre em Ajustes - Music Controls - Registration settings - Start trial (o trial é de 5 dias, depois tem q pagar os 4,99. Ainda estou no trial :) ).
  5. Caso seu ipod app esteja aberto (ou em background), feche-o e abra novamente. Pronto! seu Iphone agora funciona perfeitamente utilizando os comandos de navegação via um dispositivo bluetooth!!
Testei no meu carro e no meu home theater que também tem bluetooth. Funcionando perfeitamente e com o plus de não precisar ter nenhuma aplicação gambi pra funcionar. Ou seja, funciona perfeitamente com o player ipod nativo do iphone!

Ah, ia me esquecendo. Meu Iphone é um 3GS 16gb rodando o OS 4.0.1. 

Mais um ponto pro cydia! :)

Até!