Executando verificação de segurança...
2

Vídeo tutorial: Como está sendo programado as TabCoins aqui no TabNews

Turma, acabei de finalizar um vídeo tutorial navegando pelo código do TabNews explicando como que está sendo programado a feature de TabCoins, principalmente como iremos fazer o lastro das informações. Fora isso, eu forço alguns cenários de erro para mostrar quais garantias temos com a consistência dos dados.

O vídeo está hospedado no meu canal como não listado, espero que gostem: https://youtu.be/NkdwsljLEOc

Carregando publicação patrocinada...
1

Que vídeo mais que massa, massinha demais!!!!!! Muito obrigado por nos proporcionar um conteúdo tão valoroso e rico sensacional! Muito obrigado mister Deschamps, isso com certeza está inspirando muitas pessoas a crescer e ser melhores dia após dia (com certeza eu estou melhorando muito). Simbora contribuir como podemos!!!

1

Show! Vou ver agora. Inclusive acho interessante implementar algo parecido no curso. Mostrar na prática como usar tudo que você aprendeu em um site, software, adicionar sistemas diferentes que não são comuns, ou até mesmo como criar ideias próprias e autênticas pra tornar seu programa/website muito mais único (se fazer um vídeo separado só sobre esse assunto, tenho certeza que rende conhecimento para além dos limites da programação).

1

Sensacional meu caro! Esse seu comentário, o do gfbengel e rodrigoKulb estão lapidando muito o curso. Seria sensacional recriar linha a linha a experiência de ter desenvolvido o TabNews (e continuar desenvolvendo) não somente na parte do código, mas no que foi pensado em cada parte do projeto, desde a concepção.

1
1

Caramba @filipedeschamps já começou o curso sem avisar hahaha!!

Conteúdo de qualidade já no formato de curso 🤩️.

Fiquei com dúvida se realmente precisamos trabalhar com um cache. Uma vez fiz uma implementação parecida e a solução para não precisar sempre somar os valores foi utilizar um campo na tabela chamado último saldo (last_balance):

sequencebalance_typeamountlast_balance
1user:tabcoin55
2content:tabcoin11
3user:tabcoin510
4content:tabcoin11

Assim para saber o saldo não precisa somar todos os registros basta pegar o último registro cadastrado.

Outro ponto que fiquei com dúvida é porque o conteúdo recebe tabcoin? 😅️

1

Caramba @filipedeschamps já comecou o curso sem avisar hahaha!!

Conteúdo de qualidade já no formato de curso 🤩️.

Que massa!!! Eu tava super inseguro com a explicação porque foi feito no real-time mesmo 😂

Fiquei com dúvida se realmente precisamos trabalhar com um cache. Uma vez fiz uma implementação parecida e a solução para não precisar sempre somar os valores foi utilizar um campo na tabela chamado último saldo (last_balance):

Que abordagem massa! Pelo que entendo, isso é um cache também 😍 No caso da V2 do Pagar.me, eles possuem uma outra tabela de saldo que anota o último id somado da balance_operation. Vou conversar com eles sobre sua abordagem, obrigado por trazer aqui 🤝

Outro ponto que fiquei com dúvida é porque o conteúdo recebe tabcoin? 😅️

O conteúdo recebe TabCoin, pois é a forma que teremos de rankear os conteúdos. Você vai poder gastar suas TabCoins e parte vai para o usuário autor daquele conteúdo e parte vai para o conteúdo em sí. Quanto mais TabCoins um conteúdo tiver, melhor ele será rankeado na Home, por exemplo.

1

Fala pessoal! Tudo bem?

Pô, essa ideia de salvar o último saldo em uma coluna é muito boa e diminui bastante o tempo de leitura. Já cogitamos utilizá-la aqui no Pagar.me. Mas, como toda ideia, possui alguns tradeoffs que acabaram fazendo com que não seguíssemos com essa abordagem.

Quando discutimos um pouco mais a fundo esta ideia, percebemos que a vantagem de ter o cálculo de saldo mais rápido nos traria um custo: a escrita neste caso precisa ser serial. Dessa forma você garante a consistência das entradas e saídas. Mas, dependendo do volume de inserções na tabela de saldo, a serialização aumentará o tempo para processar a geração de saldo.

Esta solução é muito viável para os casos onde o volume de dados inseridos não é muito grande. Porém, não se provou muito escalável no nosso caso. Mesmo que utilizássemos critérios mais específicos para lock dos registros (por cliente, por exemplo), alguns casos ainda geravam gargalo.

1

Fala Galerinha Massa!

Acho que ficou pra aula 2 👨‍🏫 mostrar mais detalhes do cache implementado no Pagar.me pra gente ver melhor o tradeoff 🤓, mas algo importante para avaliar é a proporção de leituras/gravações de saldo em cada um dos dois sistemas.

Imagino que no Pagar.me o número de leituras de saldo seja um pouco maior que o de gravações, mas no TabNews o número de leituras vai ser ordens de grandeza maior do que o de gravações. Pelo menos foi o que considerei quando fiz essa sugestão na PR #462 que é bem alinhada com a sugestão do Rodrigo.

Para impedir inconsistências, poderia colocaria uma coluna a mais que seta o saldo acumulado como outdated quando outro saldo acumulado é calculado. Com isso, no início da transação, é feito o lock da linha que continha o saldo mais atual e, ao final da transação, ele é setado como outdated. Assim a escrita ocorreria de forma serial para cada usuário/conteúdo, sem risco de inconsistência.

->sequencebalance_typerecipient_idamountlast_balanceoutdated<-
...1user:tabcoinaa55true...
...2content:tabcoinbb11true...
...3user:tabcoinaa510false...
...4content:tabcoinbb12false...

O que acham dessa abordagem?

1

Sobre escrita/leitura no TabNews, não tinha parado para pensar. O que podemos especular talvez é o seguinte: sempre usaremos páginas estáticas (e mais para frente inclusive o retorno da API também deveria estar sob o efeito de cache). Mas em contra partida, cada tabcoin doada ou retirada (que seriam os "up votes" ou "down votes" de um conteúdo) irá gerar novas escritas no banco (novos lançamentos de balance_operations).

Mas independente disso, eu chutaria que por um bom tempo nada disso será gargalo, independente da estratégia adotada. Se isso for uma verdade, eu prefiro sempre utilizar a estratégia mais simples e bruta.

PS: o layout de tabelas que vocês estão usando está sensacional heim? Nota 10 😍 🤝

1

Penso que o número de leituras será muito maior do que o de escritas pelo seguinte...

Vamos partir de uma situação de cache ideal, onde nenhuma nova consulta ao banco de dados será necessária enquanto não houver nenhuma escrita.

Nesse caso, o quanto o número de leituras vai ser maior do que o de escritas irá depender somente do algoritmo utilizado para classificar a relevância dos conteúdos.

Dependendo desse algoritmo, uma única gravação (inclusão de novo conteúdo ou "curtida"), vai gerar a necessidade de reclassificar todo ou parte dos conteúdos, e para isso serão necessárias diversas leituras, não somente no conteúdo novo/alterado, mas em todos que serão reclassificados.

Só aí já serão várias leituras a mais do que escritas... Agora indo para a realidade, em que o cache demandará algumas revalidações, aumenta ainda mais o número de leituras com relação a escritas.

Resumindo... A depender do algoritmo de classificação e das estratégias de cache, teremos ordens de grandeza diferentes na razão entre leituras e gravações, mas, de qualquer forma, serão muito mais leituras.

PS: O Rodrigo caprichou mais na tabela, pois até centralizou o conteúdo... hahaha

1

Sensacional!

E você usou uma palavra que eu ainda não entendo completamente no caso de banco de dados que é serial, mas que nesse caso eu entendo que é uma coisa que precisa ser seguida da outra mandatoriamente, correto? Isso tem a ver com o termo serializable do Postgres? Tem alguma coisa nesse termo que eu ainda não consigo entender.

Algo que não precise ser serializable é mais rápido, por exemplo uma transaction pode ser configurada para não ser serializable, com o risco de retornar um erro se a ordem dos eventos não produzir o mesmo resultado se estiverem em ordens diferentes?

1

Então, o termo serial não necessariamente está ligado ao nível de isolamento serializable. Quer dizer apenas que as operações precisam estar enfileiradas, pois quando você quer criar uma operação debitando valores de uma conta, você precisa garantir que existe saldo e nenhuma outra operação irá ser executada simultaneamente.

Os níveis de isolamento são usados de acordo com anomalias que você quer (ou não) evitar ao lidar com transações no banco de dados.

Na documentação do Postgres tem uma explicação interessante sobre as anomalias e quais são evitadas com cada nível de isolamento. O serializable, por exemplo, evita todas elas, mas para isso ele exige que as operações sejam executadas de maneira isolada.

1

Estou vendo que vamos bugar o layout do tabnews. Isso é ótimo porque estamos em uma real discussão mostrando que existe uma melhoria necessária de layout.😄️

@jeanaugustoos nossa que legal receber seu feedback aqui!

Resumindo para conseguir deixar a tabela serializable vamos perder tempo na inserção, comparado com uma tabela não serializable ?

A forma que estamos fazendo de somar todos os registros para receber o saldo, o tempo é bem maior que o exemplo que informei utilizando a tabela serializable, certo?

1

Sobre o layout do TabNews, eu sugiro remover o padding a direita, e caso ficar muito apertadinho, fazer como o reddit, onde é possível clicar em "ver mais" onde abre como se fosse uma página de continuação r

1

Na PR #425, que vai ser analisada após a implementação das TabCoins, entre várias mudanças que corrigem problemas em telas pequenas, eu diminuí o padding da direita para 1px.

Depois vou subir essa versão e coloco o link aqui.

1
1
1

Ficou show!

Mas tive uma dúvida que eu acho que é pq vocês ainda não chegaram nessa etapa, mas como vai funcionar quando um usuário usa as TabCoins?

A gente vai salvar um registro (-1) ou vamos criar uma outra tabela pra mostrar os gastos? E após ele usar o TabCoin, será possível o author e os outros usuários saberem quem foi que usou TabCoins ou vai ser anônimo?

Os TabCoins vão ficar no Post e no User ou vão ficar só em um ou no outro?

Comentários vão dar TabCoins?

Tenho muitas perguntas kkkk 😅

1

Excelente pergunta meu caro! E correto, nós vamos fazer um novo lançamento com o valor negativo na mesma tabela de operações de saldo (assim como o Pagar.me também faz).

Sobre ser anônimo ou público, eu sempre voto para que esse tipo de coisa seja público, pois isso pode ser auditado por todos para principalmente conseguir identificar algum abuso. Não sabemos exatamente como fazer isso ainda, mas gosto muito da ideia 🤝

Os TabCoins (e o TabCash) é o resultado da soma das balance_operations. E esse valor vai poder ser consultado no retorno do user. Então use como o exemplo o seu usuário:

https://www.tabnews.com.br/api/v1/users/thayto

{
  "id": "4f246949-247b-4a6e-b3f1-a638ede7d924",
  "username": "thayto",
  "features": [
    "create:session",
    "read:session",
    "create:content",
    "create:content:text_root",
    "create:content:text_child",
    "update:content",
    "update:user"
  ],
  "created_at": "2022-05-19T17:11:23.205Z",
  "updated_at": "2022-05-19T17:17:21.953Z"
}

Ali dentro será retornado dois novos campos: tabcoins e tabcash.

1
1

gfbengel show!! Fico especialmente feliz com esse retorno. Digo isso porque uma ideia comum que surgiu sobre o curso era abordar algo para iniciantes, por exemplo, como começar a programar do zero. Mas o seu comentário e o do rodrigoKulb me deixou pensando bastante, se ao invés de fazer um conteúdo para iniciantes (algo que já possui muito na web), será que seria melhor fazer um curso sobre um projeto que está rodando de verdade, com situações de verdade, como o TabNews. Então nesse curso eu poderia recomeçar o TabNews, explicando em detalhes tudo como foi feito, o que eu estava pensando na época, tradeoffs, etc... coisas de um projeto que está encostrando com a vida real. Você acha que faz sentido?

1

essa abordagem parace incrível
é possível tratar de assuntos iniciais de alguma forma ao apresentar a concepção do projeto do TabNews, mas "refazer" o tabnews como um super projeto de um curso já quase que automaticamente colocaria todos alunos como possíveis contribuidores do projeto no futuro, já que de certa forma estariam "por dentro" do código e isso vira um ciclo de crescimento contínuo maravilhoso, tanto para os alunos como para o TabNews em si.
seria legal até trazer parte do pessoal que contribui no desenvolvimento pra algumas aulas como "professores convidados".

1
1
1

Muito massa a explicação! Adorei a abordagem do balance... mas fiquei com uma dúvida que talvez seja um pouco besta (sou bastante iniciante ainda)
No caso do site em produção, onde teremos várias transações realizadas, fazer a soma dos valores a cada requisição do usar não vai acabar consumindo muito recurso do banco de dados ja que seria necessario realizar a soma em vários items?

1

Victor, sua dúvida é zero besta e você está correto! O que queremos descobrir é o quanto isso vai consumir de fato. No Pagar.me eles rodaram com esse mesmo método por anos, apesar de lá usarem uma instância do RDS bem mais potente do que estamos usando (estamos com a instância mais barata possível). Vamos ver o que acontece e se ficar muito devagar rapidamente, devemos implementar o estágio 2 que é uma tabela de cache com o valor já computado (através da soma das balance_operations) 🤝

1
1
1

Obrigado Turma, Obrigado Filipe!

Entrei hoje aqui, finalmente tive um tempinho pra olhar de perto o tabnews, eu vi o vídeo e hoje o Filipe conseguiu vencer mais uma barreira que era o vídeo ter muita qualidade no conteúdo e sem precisar de um estúdio, e como ele ressaltou na ultima live, é devido ao apoio dos membros, e claro, a dedicação do Filipe!

Espero poder participar em breve como um contribuidor, esperando a poeira baixar por aqui xD

Abraços Turma!

PS: Que massa que funciona markdown aqui 🤩

1