Fazendo o Twitter Calcular Bitcoins com Ruby na Nuvem
Kemel Zaidan @kemelzaidan
#TheDevConf
ACOMPANHE COMIGO
slides.com/kemelzaidan/bitbot-qconsp/live
#TheDevConf
Kemel Zaidan
Evangelista de Tecnologia na @Locaweb
- Community Member no iMasters
- Editor chefe da Linux Magazine
- Colunista de Tecnologia
- Coord. de Projetos de Inclusão
- Ubuntu Member
- Membro do Garoa Hacker Clube
Motivações do Projeto
- Estudar Ruby
- Aprender sobre o Jelastic
Ideias
- Início do projeto no XDK;
- Ter uma maneira fácil e "mobile friendly" de conseguir uma conversão de Bitcoins;
- Que envolvesse Bitcoins;
- Que rodasse no Jelastic;
- Que ninguém tivesse feito ainda.
Código do projeto BitcoinCalc do XDK ainda está no Github: https://github.com/kemelzaidan/BitcoinCalc
Requisitos
Twitter tem várias APIs, dentre elas a de streaming (diferente da REST)
Requisitos
- Isso obrigava a programar assincronamente;
- Utilizar uma API para descobrir a cotação do Bitcoin;
- API do bitcoinaverage.com já fornecia a conversão para várias moedas.
- Ideia era deixar o mais simples possíveis
- Colocar para rodar no Jelastic
Implementação
Gems utilizadas
- tweetstream
- em-http-request
- httparty
- simple_oauth
- json
- rack
- redis
Rack
- No começo, cada framework e servidor Ruby trabalhava de um jeito.
- O Rack é uma interface que unifica a forma como frameworks e servidores Ruby conversam.
- Você pode testar um servidor/PaaS novo sem mudar uma linha do seu código. (Jelastic, Heroku, Unicorn, Puma, etc).
- Você pode testar um framework novo sem mudar de servidor (Sinatra, RoR).
- Esse conceito existe em outras linguagens: Python tem WSGI, Java tem servlets.
Reactor Pattern
Definição:
The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers".
Metáfora
- Imagine malabarismo com Threads bloqueadas (por IO), aproveitando recursos não bloqueados (CPU);
- Beneficia linguagens interpretadas que possuem GIL e acabam rodando num processador só;
- Pró: economiza dinheiro com hospedagem;
- Contra: Adiciona complexidade que pode ser desnecessária;
-
Ruby tem Event Machine, Python tem Twisted.
Problema
# Setup $conversions = 0 # Conversion currency, amount = parse_tweet("0.5 in #USD") result = convert('USD', 0.5) reply("#{amount} in #{currency} is #{result}") $conversions += 1 # Checking later reply("We have made #{$conversions} conversions so far")
Solução
# Setup $redis = Redis.connect # Conversion currency, amount = parse_tweet("0.5 in #USD") result = convert('USD', 0.5) reply("#{amount} in #{currency} is #{result}") $redis.sadd("conversions", "#{amount} in #{currency} at #{Time.now}") # Checking later reply("We have made #{$redis.scard("conversions")} conversions so far")
Programação Assíncrona:
Teoria x Prática
- Problemas nos acessos de threads a valores de variáveis
- Variáveis globais: pensar antes de usar
- No ambiente de nuvem, podem haver variáveis globais para processos ou servidores diferentes.
Código Síncrono
puts "1) Fetching data" respose_body = HTTParty.get "https://api.bitcoinaverage.com/ticker/global/all" # 1 second later puts "2) Storing fetched data" $redis.set(response_body["data"]) puts "3) Done!"
Código Assíncrono
puts "1) Fetching data" http = EventMachine::HttpRequest.new("https://api.bitcoinaverage.com/ticker/global/all").get http.errback { p '3) Not-done! Error!'; EM.stop } http.callback do # 1 second later $redis.set(response_body["data"]) puts "3) Storing fetched data" p http.response_header.status p http.response_header p http.response puts "4) Done!" EventMachine.stop end puts "2) Doing other things"
Aprendizados
Programação assíncrona
- A sequência de execução das instruções não é a mesma que estamos acostumados
- Debugar mentalmente é mais complicado
- Log tudo que for possível!!!
Outros
- Gem do Redis mimetiza a API do banco
- Possível setar um valor apenas se ele existir
Descobertas do Jelastic
- Resolve as dependências sozinho através do método padrão da linguagem (Gemfile e bundler no Ruby);
- Utiliza o Passenger como padrão (Unicorn e Puma estão disponíveis);
- Como visualizar os puts no terminal? errors.log
Hora de Testar!!!
Programador Ruby???
@kemelzaidan
kemel.zaidan@locaweb.com.br
Fazendo o Twitter Calcular Bitcoins com Ruby na Nuvem
By Kemel Zaidan
Fazendo o Twitter Calcular Bitcoins com Ruby na Nuvem
Palestra apresentada dia 27/03/2015 durante a QCon São Paulo 2015, SOLISC 2015 e no TDC Floripa, em 16 de Maio de 2015
- 2,725