Em parceria com meu amigo JP, fizemos uma aplicação para iPhone que resolve o problema de atualizar todos os telefones de celulares de São Paulo da nossa agenda do iPhone.
O problema é que em 29 de julho agora, os números de telefone celular de São Paulo ganharão um nono dígito 9. Então, se o telefone do paulista era xxxx-xxxx, agora será 9xxxx-xxxx.
E o aplicativo 9D9 tá aí pra resolver isso:
www.9d9.com.br
Colocamos no ar essa semana, mas a Apple ainda não aprovou.... aguardemos mais uns dias....
primeira iPhone App - Novo Nono Dígito para Celulares de São Paulo
Vendo corretamente os caracteres especiais com UTF8 no Putty
Quando uso o Putty para me conectar com servidores linux remotos, e lá dentro uso caracteres especiais (como acentos da língua portuguesa). muitas vezes tenho problemas para visualizar estes caracteres.
Por exemplo, quando faço um select no BD Postgres, e no resultado da query tem caracteres especiais codificados em UTF8, fica tudo feio....
Para resolver isso, abra o Putty. Na janela inicial, lá no menu Window > Translation, defina o item Remote Character Set para "UTF-8". Só isso.
Abcs
Google Calendar feito com Grails
Eu não escrevo há algum tempo, eu sei....sinto muito...... mas o tempo tem estado muito curto. Mas hoje vi um post que não pude deixar de repassar por aqui, pois vale a pena....
O post é de Craig Burke mostrando uma aplicação Grails, desde a modelagem de domínio até plugins usados, que simula o Google Calendar. Bem interessante:
Parte 1: http://www.craigburke.com/blog/2012/02/09/creating-google-calendar-in-grails-part-1-the-model/
Parte 2: http://www.craigburke.com/blog/2012/02/16/creating-google-calendar-in-grails-part-2-displaying-the-calendar/
Abcs a todos.
Montando um super PC de alta performance
Um amigo me mandou um email me dando dicas para montagem de um PC de alta performance. Ele escreveu o que fez para montar a máquina dele, que disse ter ficado um verdadeiro avião. Ficou tão bom o email que aqui vai ele. Valeu Paulo Goes......:
"Felipe,
O coração do sistema é um processador i7 2600K. É o processador mais potente para uso pessoal (os outros i7 já são workstation ou servidor). Este processador incorpora um conjunto de instruções gráficas, de modo que dispensa o uso de processador gráfico, mesmo na placa mãe. O i7 2600 (sem o K) é um pouco mais barato, possui a mesmíssima capacidade de processamento, só não é “overclockable” e tem uma versão anterior do driver gráfico Intel (é uma excelente opção para reduzir um pouco o custo). Os i5 (acho que o i5 equivalente é o 2500/2500K) têm potência equivalente (e a mesma relação K/sem K dos i7), mas não suportam hiperthreading. Com hiperthreading as 4 CPUs do processador dual core aparecem como oito para o sistema operacional, proporcionando um ganho de paralelismo (se e somente se o seu mix de aplicações demandar tantos processos concorrentes). Assim os i5 são também excelentes opções para baratear o custo.
O componente seguinte é a placa mãe. Atualmente estou bem exigente neste quesito, e só estou comprando ASUS ou Intel. As Intel estão mais baratas, e bem interessantes. No entanto, eu tinha alguns requisitos adicionais:
- queria 16G de memória – isto hoje só é economicamente viável com placas que tenham 4 bancos de memória. A maioria das placas mais baratas só estão vindo com 2 bancos, mas as memórias de 8G estão ainda proibitivamente caras;
- tenho alguns dispositivos IDE, e as placas mais modernas e baratas só têm SATA
- meu adorado monitor ainda é VGA, e as placas mais modernas e baratas têm apenas DVI/HDMI, e eu não queria usar conversores
- SATA 6GB/s – as placas mais modernas têm interface SATA de 6GB/s. Na prática, não faz a menor diferença, porque os HDs não conseguem entregar nem os 3GB/s do SATA “II”. No entanto (ver abaixo), uma das principais “turbinas” do meu “avião” é um disco SSD que atinge com facilidade este throughput, de modo que SATA 6GB/s era mandatório.
- gosto de placas ATX – nada de micro-ATX ou mini-ATX (embora, na prática, sejam quase equivalentes)
- mouse, teclado, cam, impressora, scanner, iPhone, disco externo, pen-drives, tudo lá em casa é USB. Desejo uma placa mãe com o maior número possível de USBs externas.
No mais, escolher uma placa é uma combinação de marca, com os slots/dispositivos que você necessita, mais aqueles que você acha que vai precisar no futuro. Neste sentido, achei que umas portas USB 3 seriam altamente desejáveis, e que um firewire não seria demais. Aí, é entrar no Boadica, filtrar por fornecedor, sortar por valor, e ir olhando as configurações até achar a primeira que te satisfaça. Escolhendo uma, entrar no Tomshardware, para ver se há algum comentário negativo sobre esta combinação processador/placa. Acabei escolhendo uma Asus, mas nem lembro o modelo agora.
O terceiro componente importante é um SSD de 120G da OCZ (Vertex 3). Este é um componente ainda complicadinho. Memórias SSD têm um burnout depois de alguns milhões de escritas (ou seja, têm uma vida útil limitada). As controladoras mais modernas (Sandforce) maximizam a vida útil distribuindo igualmente as atividades de escrita por setores diferentes do disco, evitando assim, por exemplo, que o começo do disco estrague antes do final. Uma boa controladora também é essencial para conseguir os tais 6GB/s de throughput. Os OCZ são as Ferrari dos SSD. Tem uma outra linha (que não é Vertex) que é um pouco mais barata, mais ainda muito boa. Me aconselharam a evitar os Kingston (bem mais baratos) e me disseram que os Corsair talvez sejam bons. Li alguns artigos dizendo que os Samsung estão causando sensação por serem mais baratos e tecnologicamente competentes, mas não quis arriscar. A idéia é instalar o Windows neste SSD, conseguindo assim uma baita velocidade nos boots e na carga de qualquer programa/OS component. Configurar corretamente o Windows para maximizar o benefício e a vida útil do SSD é uma arte obscura, na qual ainda estou me iniciando (deixa o paging ou não? temporary IE files? temp files? como tirar os dumps do Windows do SSD? etc.).
O gabinete é outro aspecto que eu tomo cuidado. Gabinetes devem ser silenciosos, práticos para montar (por exemplo, não necessitam de parafusos para fixar os HDs) e bem ventilados. Já a alguns anos que venho usando os gabinetes CoolerMaster. Sempre usei a linha básica (Elite), mas este eu comprei da linha ultra-silenciosa (Sileo), que vem também com duas ventoinhas (os Elite vêm com uma só – a gente sempre pode acrescentar ventoinhas, mas as originais da CoolerMarster são hiper-silenciosas).
A fonte é um componente fundamental para a saúde do equipamento. A qualidade das fontes caiu, e fontes anteriormente de boa qualidade (como as Seventeen) hoje são consideradas suspeitas. Comprei uma Coolermaster 600W reais, meio overkill para o meu equipamento (uma de 450W já bastava) porque não tenho nenhum periférico/placa no meu ambiente que não seja um “array” de HDs (que consomem bem pouca energia), mas, pensando no futuro...
A memória, comprei Corsair 4x4GB. Eu sempre usei Kingston (que custa metade do preço) sem problemas, mas meu filho me convenceu a comprar as Corsair... provavelmente bobagem.
O componente final é um HD de 1TB (ainda o menor custo por byte armazenado), para se juntar aos meus atuais 2,5TB.
Um aspecto interessante é que eu não jogo games e não faço processamento gráfico, de modo que não tenho placa de vídeo há anos (uso onboard ou, agora, inprocessor).
Finalmente, como comprei: Primeiro, eu uso o Boadica para estabelecer referência de preços. Os preços do Boadica são muito bons, e normalmente não consigo estes preços nem na Santa Efigênia aqui em sampa. Como estava sem tempo, minha estratégia desta vez foi adquirir na Internet. Para começar, identifiquei no Buscapé os fornecedores web mais confiáveis para componentes (nenhum é muito confiável, nem inspira muita confiança, de modo que é preciso ser um pouco tolerante e aceitar algum risco aqui). Pré-selecionei uma meia dúzia, fiz uma análise de preços, e acabei ficando com 3 (Atera, Superbalão, e Kabum). Comprar em loja, e ainda mais parcelado (12x) se afasta um pouco dos preços do Boadica, mas é uma forma de diminuir o risco e o impacto imediato no bolso). Você não precisa fazer todas as compras na mesma loja, mas também não deseja comprar um componente em cada loja (maior risco de problemas e despesas de entrega), assim, tem que fazer algumas simulações para ver qual fornecedor consegue o menor preço médio dos componentes combinados. Comprei o gabinete, a fonte e as memórias na Kabum, e o processador, a placa mãe, e o HD no Superbalão. O SSD arrisquei um pouco mais e comprei no mercado livre.
A compra no mercado livre foi a mais bem sucedida, embora o mercado pago tenha feito uma bobagem e faturado duas vezes o meu cartão. Escrevi para o vendedor, e ele em algumas horas estornou a venda (o mercado pago não ajuda você, você tem que se virar), e em menos de 24h após a compra o SSD estava lá em casa. Com a Kabum tive vários problemas por conta da operadora American Express (nunca tinha usado e nunca mais usarei). Cancelei a compra, refiz pelo Visa, e 48h depois recebi a mercadoria, sem problemas. No geral, fiquei muito satisfeito com a Kabum, por causa do comportamento deles nestes dificuldades com a AMEX. O pior foi o Superbalão. A entrega levou uma semana (após meu cartão ter autorizado), e o HD chegou sem lacre e arranhado (parece que já havia sido instalado em algum PC antes). Deu algum trabalho para trocar (eles queriam que eu pagasse o frete, e eu tive que chiar muito), e ainda estou aguardando receber a troca.
That’s it. Isso tudo requereu muita pesquisa, conversa, visitas a fóruns e o escambau. A parte mais chata são sempre estas relações comercias selvagens do Brasil, combinadas com a estupidez da Amex. Por uns 10K reais faço tudo de novo prá você..."
Isso é que é dica..... Sensacional....
Grails de alta performance - parte 2
Este post faz parte de uma série que estou escrevendo sobre técnicas para fazer uma aplicação grails de alta performance. Estou usando uma aplicação de exemplo, para demonstrar estas técnicas. Esta aplicação se chama GPerform, e está disponível no GitHub, e é uma espécie de Twitter + Instagram (em menor escala, naturalmente), onde usuários enviam posts de texto curto + foto.
Na parte 1 desta série, eu mostrei a primeira prática para se desenvolver uma aplicação grails de alta performance: Não usar Collections para as relações hasMany.
Neste post vou mostrar os plugins que usei.
1) Spring-events plugin:
Este plugin dá a possibilidade de publicar eventos via Spring, de forma assíncrona.
Para instalar o plugin, basta executar "grails install-plugin spring-events".
Eu usei este plugin para lançar um evento indicando que alguém enviou um novo post no sistema, e que, portanto, o sistema precisa processar a foto (criando uma foto com tamanho (kb) menor, e outras fotos thumbnail).
Mas, para não deixar o usuário esperando enquanto o sistema processa as fotos, e assim dar uma impressão de muita velocidade de resposta para o usuário, eu quis fazer este processamento de forma assíncrona, dando uma resposta para o usuário quase que imediata após o envio do seu post.
A action que recebe o envio do post do usuário, com texto + foto, apenas grava a foto num diretório, salva a entidade Foto no banco de dados, e lança este evento assíncrono no Spring, retornando a resposta imediatamente para o usuário (sem processar a foto neste momento). Veja:
def compartilhar = {
String msgErro = ""
if(!session.usuario){
redirect(controller:'home')
return
}
// Pega a foto do formulario e salva no diretorio para ser processada
MultipartFile fotoOriginal = request.getFile('fotoOriginal')
String extensao = identificaExtensao(fotoOriginal)
String nomeArquivo = RandomStringUtils.random(10).encodeAsSHA256() + extensao
try {
File destino = new File(ConfigurationHolder.config.gp.fotos.originais.folder + File.separator + nomeArquivo)
fotoOriginal.transferTo(destino)
// Salva uma isntancia do objeto de metadados Foto
Foto foto = new Foto(params)
foto.autor = Usuario.get(session.usuario.id)
foto.nomeArquivo = nomeArquivo
if(foto.save(flush:true)){
// metodo adicionado pelo spring-events Plugin
publishEvent(new FotoSubidaEvent(new Expando(id:foto.id)))
flash.message = "Foto enviada com sucesso. Aguarde processamento."
redirect(action:index)
}
else{
if(destino.exists()) destino.delete()
msgErro = "Erro ao salvar os dados da foto."
render(view:'index', model:[msgErro:msgErro, foto:foto])
}
} catch (IOException ioe) {
msgErro = "Erro ao fazer upload do arquivo."
} catch (IllegalStateException ie) {
msgErro = "Erro ao fazer upload do arquivo."
}
}
Veja que o método importante aqui é o "publishEvent()", que publica o evento FotoSubidaEvent (eu sei que o nome ficou feio, mas ...). Pronto, o evento foi publicado.
Agora, precisamos criar uma classe que vai ser o Listener deste evento. A maneira mais fácil que encontrei foi criar uma classe de serviço que implementa "ApplicationListener
2) Springcache plugin:
Este plugin faz uso do projeto Spring Cache, e permite que se faça:
Para usar este plugin, basta instalar usando o comando "grails install-plugin springcache". Em seguida, coloquei uma anotação na action do meu controller (na action que quero que a resposta fique em cache):
@Cacheable("recentesCache")
def recentes = {
log.info "Executando action 'recentes' e por isso nao ta usando o cache agora."
def recentes = buscaFotosMaisRecentes(20)
[fotosMaisRecentes:recentes]
}
Agora o problema passa a ser como renovar o cache quando um novo post for enviado por um usuário do site. Para isso, basta limpar o cache (matar o cache) quando um novo post for inserido. No meu caso, o que fiz foi o seguinte: quando um usuário envia um novo post (que é um texto + foto), o controller recebe esta requisição, faz algumas verificações, salva a foto num diretório para ser processada posteriormente (de forma assíncrona -- falo sobre isso mais tarde), e grava os dados da entidade Foto no banco de dados (que são os metadados sobre a foto e o texto do post do usuário). Quando o sistema for processar a foto de forma assíncrona, aí sim a foto está pronta para ser mostrada no site, e é neste momento que eu preciso limpar o cache. O método que processa a foto e limpa o cache é um método de uma classe de Serviço (FotoService). Veja abaixo:
@CacheFlush("recentesCache")
void onApplicationEvent(FotoSubidaEvent event) {
if(log.isInfoEnabled()) log.info "Executando evento FotoSubidaEvent..."
Foto foto = Foto.get(event.source.id)
if(foto){
// processa a imagem da foto
}
}
Assim que este método for executado pela aplicação, o cache será limpado (jogado fora), pois este método tem a anotação @CacheFlush("recentesCache"). Veja que usei o mesmo nome "recentesCache" para indicar qual cache quero limpar.
Perceba também que este é aquele método "onApplicationEvent()", citado no item 1 acima, usado pelo Spring quando o framework detecta o lançamento do evento do tipo FotoSubidaEvent.
Pronto. Da próxima vez que a action HomeController.recentes() for executada, o Springcache vai ver que o "recentesCache" não existe mais, aí vai executar a action, pegar seu resultado e colocar em cache novamente. E enquanto este cache existir, a action não é executada, e ao invés disso, o conteúdo do cache é enviado para o usuário.
Um pequeno detalhe deste plugin é que ele tem uma configuração padrão que indica que o cache deve existir por apenas 120 segundos. Como era muito pouco para o meu caso, então configurei para que o cache vivesse por 3600 segundos. Veja como:
springcache {
defaults {
eternal = false
diskPersistent = false
timeToLive= 86400
}
caches {
recentesCache {
timeToLive= 3600
}
}
}
Ficamos por aqui com este artigo que já tá longo. Ainda falta coisa pra falar, como resources plugin, cache-headers plugin, cached-resources plugin e zipped-resources plugin. Até a próxima.
Lembre-se que você é bem vindo para contribuir com esta aplicação de exemplo GPerform via o GitHub. Abcs a todos.
GPerform: uma aplicação de exemplo com PERFORMANCE na alma
Venho pensando num tema legal para escrever um post. Aí resolvi dar uma atualizada, ler um pouco, ver umas apresentações, ..... E uma coisa que tem me interessado muito ultimamente é o assunto performance. Como uso muito Grails, então o assunto seria Grails e Performance. Então vamos lá.
Depois de algumas leituras, acho que juntei diversas dicas, plugins, e técnicas que vão fazer uma aplicação grails voar em alta velocidade. Mas não queria apenas ficar na leitura, pois sabemos bem que a teoria é uma coisa, na prática.....
Então botei a mão na massa e resolvi criar uma nova aplicação que chamei de GPerform (Grails Performance). Criei uma aplicação (na verdade está sendo criada ainda) que é uma espécie de Twitter + Instagram (em menor escala, naturalmente). Você manda uma foto, com comentário. Você pode seguir pessoas, e pessoas podem te seguir. Você pode avaliar fotos como boa ou ruim. Tudo é público.
A aplicação é 0.1, ok? Mas está disponível no GitHub. Seja bem vindo para contribuir se quiser (estou dando meus primeiros passos com o Git, então paciência comigo....).
A primeira coisa a fazer foi criar o modelo de dados, e aí já começam as dicas para uma melhor performance da sua aplicação: Não usar Collections para as relações hasMany. E mais que isso: acabar com as relações diretas entre duas classes para os casos many-to-many e one-to-many. Pois é, parece estranho. Mas tem fundamento.
Para esclarecer o fundamento, vou dar um pequeno exemplo. Imagina:
class ContaCorrente{
String numero
String agencia
static hasMany = [transacoes: Transacao]
}
class Transacao{
BigDecimal valor
static belongsTo = [conta: ContaCorrente]
}
Imagine que você queira usar as facildades que o Grails dá para gerenciar esta relação one-to-many. Ou seja, você vai querer usar o método conta.addToTransacoes(t) que está disponível para você, claro.
Mas imagine quantas transações tem numa conta corrente al longo de um ano. Se você tiver 30 transações por mês, no ano serão 360. Ou seja, no final do ano, quando o seu sistema for adicionar mais uma transação na conta do usuário, ele irá buscar as 360 transações para montar a collection "conta.transacoes" e só depois irá adicionar a nova transação nesta collection, para aí gravar esta alteração na collection no banco de dados. Se inicialmente você queria fazer apenas um insert, você acaba fazendo um select que retorna 360 itens pra memória (que você não vai usar nenhum deles), um insert da nova transação, e um update da ContaCorrente (pois o GORM atualiza o campo version deste objeto pai).
É ou não é coisa demais, e é muito provável que a performance da aplicação será seriamente afetada?
Para resolver isso, Burt Beckwith sugere, em uma apresentação na infoQ, que não se use a relação one-to-many com o hasMany. Que se faça apenas o outro lado da relação, que é o many-to-one. Qual é a perda disso? Você não vai ter o método addToTransacoes(). Mas isso é fácil de resolver. E também não vai ter um atributo "transacoes" que te retorna todas as transacoes da sua conta (você provavelmente não iria usar nunca - nem deveria). (veja um post interessante sobre isso) Por exemplo:
class ContaCorrente{
String numero
String agencia
def buscaTransacoesRecentes(int qtde){
Transacao.executeQuery('from Transacao t where t.conta = :c order by t.dateCreated desc', [c:this], [max:qtde])
}
def adicionaTransacao(BigDecimal valor){
new Transacao(valor:valor, conta:this).save()
}
}
class Transacao{
BigDecimal valor
Date dateCreated
ContaCorrente conta
}
Pronto. Simples assim. Você agora conseguiu ter apenas o seu único insert que você queria. Sem selects desnecessários, e sem update desnecessário (não estou contando com o select da ContaCorrente, mas tbem não contei com ele ali em cima). Veja que eu criei métodos na classe ContaCorrente para adicionar uma nova transação e para buscar as mais recentes.
Acho que tá bom por hoje né? Terei que escrever outros posts para contar tudo. Tem ainda o uso de diversos plugins, como por exemplo: springcache, spring-events, resources, cache-headers, cached-resources, zipped-resources, e por aí vai. Já já eu volto.
Dicas e passo a passo para iniciar com o Amazon Web Services - AWS (em inglês)
Estou começando a fazer uns testes com os servidores da Amazon, o Amazon Web Services. Aí descobri umas dicas e passo a passo com boas informações:
http://bristle.com/Tips/CloudComputing.htm#aws
Abcs a todos.