Closed aleborba closed 10 years ago
Acho que faz sentido para o postmon. :+1:
Quais dados seriam interessantes de colocarmos no retorno?
Seria interessante ter os dados informados na tabela do IBGE
exemplo:
http://www.ibge.gov.br/home/geociencias/areaterritorial/area.php?nome=Barreiras
Exemplo de retorno do buscarcep.
Pessoal, para esta issue, qual caminho se adequa mais ao rumo do projeto?
O que acham?
Os dados que tem no buscarcep são:
ibge_uf=29 -> UF no XLS
ibge_municipio=292200
ibge_municipio_verificador=2922003 -> UF_MUNIC
O ibge_municipio
deve ser UF_MUNIC[:-1]
, mas não tenho certeza disso.
Tem mais dados úteis nesse XLS? Vale a pena criar rotas /ibge/...
ou só adicionar esses campos junto com o resultado dos CEPs é suficiente?
Imagino que a criação ou não de nova rota deva ser decidida em função da "proximidade" da informação. Se for necessário executar uma requisição externa ao servidor do postmon para buscar a informação, mesmo que nem sempre (se existir a possibilidade dela estar cacheada no Mongo), então deve ser fornecida nova rota, pois quem não precisa da informação não deve ser prejudicado com a latência de uma nova round-trip no server, e mesmo o server não precisa gastar esse esforço se não for necessário.
Agora, se forem utilizadas informações locais direto do MongoDB (no caso de implementar uma rotina que processa o XLS de tempo em tempo, armazenando de uma forma indexada no Mongo, por exemplo) então não existiria problema em adicionar a informação diretamente nas rotas existentes.
Gosto da ideia de uma nova rota. Mas não sei se acho legal utilizar /ibge/
. Penso que algo mais "abstrato" ficaria mais "elegante". ;)
Sobre uma rota mais abstrata, acho que iremos esbarrar em um problema, pois a informação que seria fornecida pela rota ("cód ibge") é especificamente relacionada ao "ibge", não sei se se encaixa em outra abstração. O que vocês acham? Conseguem pensar em outras possibilidades?
@aleborba, sua preferência a nova rota tem relação com o mecanismo interno de coleta e cacheamento do dado? Em outras palavras, você já deu preferência ao método que faz a busca sob demanda e cacheia no Mongo, similar ao que ocorre hoje com o CEP?
exatamente @samuelgrigolato, eu tava pensando nisso. :)
Mecanismo interno: utilizar as URLs abaixo de forma similar ao CepTracker, e cachear o resultado no mongo.
Para município: http://www.ibge.gov.br/home/geociencias/areaterritorial/area.php?nome=Araraquara&codigo=&submit.x=-162&submit.y=-313 Para UF (não tem filtro, o parse mesmo terá que buscar a linha correta): http://www.ibge.gov.br/home/geociencias/areaterritorial/principal.shtm
O que acham? Vale a pena investir tempo nisso?
Me dá medo esses parâmetros "submit.x" e "submit.y", ou são marretas ou são mecanismos antibot. Tirei eles da query string e a consulta continua funcionando (menos mal, devem ser marretas), só que não testei com uma tsunami de requisições em uma pequena janela de tempo ^^.
@samuelgrigolato não é bom confiar nisso, mas usando o nome=%
retorna todos os resultados:
http://www.ibge.gov.br/home/geociencias/areaterritorial/area.php?nome=%
Sinto cheiro de SQL injection
O nome=%'
retorna os resultados com '
. Provavelmente estão tratando as aspas, mas esqueceram do %
.
Realmente teremos que fazer o papel deles e tratar do nosso lado, para não prejudicar a performance do próprio servidor do postmon ao receber uma resposta desse tamanho. Valeu a observação!
Também não gosto muito da rota /ibge
. São dados sobre estados e cidades, não necessariamente vem tudo do IBGE.
Um exemplo disso é o DDD de cada cidade (uma coisa importante pra mim), que o postmon não tem mas caberia facilmente nessa rota que está sendo criada.
O problema de utilizar o conceito "abstrato" é que, ao obter dados de vários serviços diferentes, o usuário (e o servidor do postmon) é prejudicado com o overload de requisitar dados de vários lugares. Uma opção seria usar rota abstrata e permitir alguns parâmetros de switch, por exemplo "/cidade/{nome}?dados=todos", "/cidade/{nome}?dados=ibge+ddd", "/cidade/{nome}?dados=ibge".
Os dados são pré-processados, seria uma chamada no mongodb. O overhead é só de rede, mas com essa quantidade de dados é irrelevante.
Concordo que aumenta um pouco a complexidade para integrar esses dados em registros unificados.
O DDD foi só um exemplo, aposto que tem outros dados importantes para cada cidade. Gosto da opção de filtrar o que quero de resposta.
2013/11/1 Samuel Lopes Grigolato notifications@github.com
O problema de utilizar o conceito "abstrato" é que, ao obter dados de vários serviços diferentes, o usuário (e o servidor do postmon) é prejudicado com o overload de requisitar dados de vários lugares. Uma opção seria usar rota abstrata e permitir alguns parâmetros de switch, por exemplo "/cidade/{nome}?dados=todos", "/cidade/{nome}?dados=ibge+ddd", "/cidade/{nome}?dados=ibge".
— Reply to this email directly or view it on GitHubhttps://github.com/CodingForChange/postmon/issues/56#issuecomment-27565884 .
Seriam pré-processados se fossem obtidos do XLS, mas pelo que eu entendi (vide comentários acima do @aleborba) faríamos um mecanismo de busca da informação via HTTP no serviço do site do IBGE, e utilizaríamos o mongo apenas para o cache, de forma similar ao que ocorre com o CEP. Desse modo, o overhead passa a ser uma requisição externa, e deixa de ser irrelevante.
Complementando, concordo que no caso do pré-processamento do XLS, os dados poderiam ser incorporados em qualquer rota existente, sem prejuízo na performance.
No final, temos que analisar o que é melhor para ambos os lados :)
Alê Borba
Twitter: @ale_borba Linux User #506836 Blog: http://www.aleborba.com.br gTalk: ale.alvesborba@gmail.com TUX-ES Member. www.tux-es.org PHP-SP Member. www.phpsp.org.br Dojo-SP Member. www.dojosp.org Python Meet Up Organizer. credencial.imasters.com.br/encontro-grupy-sp
Em 1 de novembro de 2013 11:48, Samuel Lopes Grigolato < notifications@github.com> escreveu:
Seriam pré-processados se fossem obtidos do XLS, mas pelo que eu entendi (vide comentários acima do @aleborba https://github.com/aleborba) faríamos um mecanismo de busca da informação via HTTP no serviço do site do IBGE, e utilizaríamos o mongo apenas para o cache, de forma similar ao que ocorre com o CEP. Desse modo, o overhead passa a ser uma requisição externa, e deixa de ser irrelevante.
Complementando, concordo que no caso do pré-processamento do XLS, os dados poderiam ser incorporados em qualquer rota existente, sem prejuízo na performance.
— Reply to this email directly or view it on GitHubhttps://github.com/CodingForChange/postmon/issues/56#issuecomment-27566446 .
Já existe alguma rotina "em batch" no postmon? Ou pelo menos existe a intenção em permitir tal mecanismo? Se sim, eu acho que a melhor opção é o pré-processamento mesmo, o TTL poderia ser bem alto (não vejo essa informação mudando com frequência) e ficaria mais transparente para o utilizador, além de novas rotas para "cidade" e "uf" poderíamos incorporar facilmente na própria rota do CEP.
Acho que já me perdi na conversa. =)
Usando esse serviço do IBGE, podemos fazer esse request para nome=%
e manter em cache por um bom tempo. Ou até buscar todos os códigos (tem isso no XLS) em background e salvar o resultado.
Pelo que entendi, de informação adicional só tem a área territorial nesse serviço do IBGE. Dá pra usar como base o XLS e adicionar outros dados nos registros conforme necessário.
Tem ~5k municípios, dá pra buscar todos os códigos no IBGE em background, nem deve impactar o servidor.
Ainda não tem rotinas sendo processadas em background, mas faz sentido ter. A forma mais fácil de fazer isso é um cronjob, mas tem opções no Python pra isso também...
@iurisilvio++
Não tenho muita familiaridade com o ecossistema python, dei uma pesquisada e achei isso aqui: http://pythonhosted.org/APScheduler. Seria a opção mais adequada?
Achei essa também http://docs.python.org/2/library/sched.html, mas senti falta de um mecanismo para executar "repetidamente", sem precisar agendar a próxima na própria execução da rotina. O APSScheduler tem isso: http://pythonhosted.org/APScheduler/intervalschedule.html
Celery com periodic_task
import celery
@celery.task.periodic_task(run_every=timedelta(hours=5))
def do_anything():
print "I run every 5 hours"
$ celeryd -l info &
Pessoal, só pra reunir o que temos até agora:
É isso? Alguém tem algo a adicionar (ou a discordar) ou já dá pra por a mão na massa?
Acho que é isso ai mesmo @samuelgrigolato.
Algo a acrescentar/remover aqui @iurisilvio @pbalduino @ihercowitz?
@aleborba já estou implementando (na medida que o tempo livre permite ^^)
Esbarrei em uma coisa interessante: a URL do IBGE para estados não tem a informação "sigla", apenas o nome, logo não tem como "buscar" a UF pela sigla para fazer o update no mongo. Para resolver esse problema pensei em três opções:
1) Criar um script que carrega previamente (de forma 'hardcoded') os estados (sigla e nome) na base, de forma que o script de track do Ibge consiga realizar o find pelo nome. 2) Realizar primeiro a carga de cidades, montando um dicionário de "código UF" > "sigla" a partir dessa carga (nessa consulta tem o código e a sigla da uf), e depois na carga de estados utilizar esse dicionário para fazer o "lookup" da sigla. 3) Procurar uma outra fonte para realizar a carga dessa informação (acho desnecessário, estados não mudam assim tão frequentemente, rsrsrs)
Qual solução preferem?
Isso aí mesmo. Só não acho necessário rodar isso todo dia, mas sendo só 2 requests, tanto faz. Se alguma hora tiver que rodar pra cada cidade, aí vale a pena pensar nisso.
@samuelgrigolato acho q a 2 é a menos "workaround", não? :)
:+1: pra opção 2 também.
@aleborba Considerando que o conceito de UF, em sua essência, não é dependente do de cidade (apenas possui relação), o fato de precisar carregar as cidades para saber a sigla de uma UF (núcleo da solução 2) também tem um "quê" de workaround na minha opinião, mas concordo com vocês que é a solução mais "limpa" das três, pois na prática não vai existir UF sem cidade e essa lógica vai evitar a necessidade de um hardcode ou uma nova dependência externa apenas para obter essa informação.
Blz pessoal! Conforme for prosseguindo vou postando aqui o andamento. Como é minha primeira contribuição nesse repositório, se fosse possível gostaria de receber alguns feedbacks antes mesmo de um eventual pull request, para ir caminhando de acordo com a expectativa. Vou referenciando os commits do meu fork aqui, =].
:hammer: :)
Dêem uma olhada aí quando der!
Uma coisa que já vou avisando que não sei se ficou bom: os novos métodos que adicionei no "database.py". Não sei se ficaria melhor refatorar para 'orientar mais a dados' e não criar essas funções com nomes de entidade de negócio na interface desse módulo.
Da forma que está já dá pra rodar com "ipython IbgeTracker.py", adicionei um modo "standalone" igual tem no PostmonServer. Já adiciona ou atualiza no mongo conforme necessário, nas bases 'ufs' e 'cidades' respectivamente. A partir de então os routes 'cep', 'cidade' e 'uf' incorporam essas informações no retorno. Atenção especial também para os nomes que usei no retorno do cep, 'estado_info' e 'cidade_info', fiz isso para não trocar o atributo 'estado' e quebrar a compatibilidade (o que iria exigir uma v2 na API =S).
Tem uma coisa que está faltando: adicionar o suporte para rodar com o celeryd, mas não acho que isso vá levar muito tempo, e também não impacta na lógica!
Durante o desenvolvimento lembrei que existem cidades com mesmo nome em estados diferentes, logo a route para cidade acabou que ficou assim: '/cidade/sigla_uf/nome'.
Algumas URLs que funcionam:
:+1:
Adicionei o suporte ao Celery. Para rodar (depois de executar o pip):
celery worker -B -A PostmonTaskScheduler -l info
O "-B" é pro Celery rodar o "celery beat" junto ao worker. O "beat" é o responsável por agendar as periodic tasks.
Usei como "broker" o MongoDB, visto que já existe essa dependência no projeto. Ele está usando um database chamado "kombu_default".
Sugiro mudar o timedelta para "minutes=1" ao invés de "days=1" para testar, por motivos óbvios =D.
Acabei de lembrar que não rodei o make test =S, já já vem um novo commit com os ajustes pro pep8.
Pronto.
Tenho mais uma observação. O Celery cria um arquivo no diretório onde o beat é executado, chamado celerybeat-schedule (é onde ele armazena os últimos timestamp de execução, algo assim). Inicialmente eu pensei que adicionar no .gitignore já resolveria (para evitar ter que adicionar uma configuração a mais no Celery pra jogar esse arquivo em outro lugar da máquina), só que o make test está tentando compilar esse arquivo e obviamente não consegue. Tem algum lugar pra fazer o test do pep8 ignorar esse cara? Ou esse tipo de coisa é resolvido de outra forma?
Sabe alguma forma de resolver isso @rochacbruno?
@aleborba @samuelgrigolato é possivel passar como parametro o caminho onde o Celery beat irá criar o arquivo de schedule http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html#starting-the-scheduler
celery beat -s /home/celery/var/run/celerybeat-schedule
OU vc pode configurar no make para o pep8 ignorar o arquivo
pep8 --exclude='*/a/foo*' /path/to/dir
ou seja,
pep8 --exclude='*celerybeat-schedule*' /
Coloquei o arquivo no exclude do pep8, funcionou!
Testei também passando um caminho customizado (via parâmetro '-s') e funcionou também! Ou seja, o usuário pode escolher a forma que ele quer usar.
Corrigi também a autenticação com o broker MongoDB, pois lembrei que no database.py existe uma forma de informar parâmetros de autenticação via variáveis de ambiente.
A implementação foi feita. Mas tive problema pra colocar o celery e vou precisar de ajuda. Vou deixar a issue aberta até resolvermos :)
@aleborba o problema é em alguma permissão. Se você rodar o supervisord como root, funciona (não é recomendado).
Sei que o supervisord precisa de acesso no /var/run e no /tmp, você sabe melhor que eu como estão as permissões na máquina do postmon.
@iurisilvio então cara, na verdade o supervisord rodou, acho q eu agarrei no celery mesmo. Amanha a gente faz um hangout e ve isso direitinho, pode ser? cc/ @samuelgrigolato
@aleborba se puder ser depois das 20 horas, eu estarei online.
Up And Running! ;)
Pessoal, Surgiu uma solicitação via twitter, do João Drummond, de fornecermos os dados de estado e municipios do IBGE, mas especificamente o código IBGE deles, pois isso é usado para geração de NFe. O que acham de implementarmos uma nova rota para isso? O XLS com os dados é este: