// adicionar $1
Golang
Se fosses tu a escrever testes unitários para o teu código, quais escreverias? Que casos extremos verificarias?
De onde obter o ID do evento para a idempotência e onde gerá-lo?
Onde armazenou os logs, qual pacote de logging usou no código e como os logs foram do stdout para o Elasticsearch?
func (r *PayoutRepository) Payout(advertiserID, partnerID string, amount float32) error { advertiser, err := r.find(advertiserID) if err != nil { return err } partner, err := r.find(partnerID) if err != nil { return err } advertiser.Balance -= amount partner.Hold -= amount partner.Balance += amount if err := r.save(advertiser); err != nil { return err } if err := r.save(partner); err != nil { return err } r.totalPayouts++ return nil }
Como entender a nível SQL que já existe uma chave de idempotência? Como usar ON CONFLICT?
Fale sobre o projeto/vaga: stack de tecnologias, tarefas da equipa
O que acontecerá com o ID na caixa de saída se a transação não for confirmada?
func (p *Pool) Stop() { p.mu.Unlock() // Agora é seguro fechar o canal close(p.tasks) // sinal aos workers: não haverá mais tarefas, leia o restante p.wg.Wait() // esperamos que todas as goroutines terminem p.cancel() // cancelamos o contexto por precaução fmt.Println("Pool parado.") } // ForceStop força a parada de todos os workers sem esperar que as tarefas terminem. // Os workers serão interrompidos imediatamente através do contexto. func (p *Pool) ForceStop(timeout time.Duration) { fmt.Printf("Parando forçosamente o pool (timeout: %v)...\n", timeout) // Bloqueia a adição de novas tarefas p.mu.Lock() p.isOpen = false p.mu.Unlock() // Fecha o canal para que os workers não peguem novas tarefas close(p.tasks) // Cancela o contexto – isso interromperá todas as tarefas em execução p.cancel() // Dá um tempo limitado para finalizar done := make(chan struct{}) go func() { p.wg.Wait() close(done) }() select { case <-done: fmt.Println("Pool parado de força (todos os workers terminados)") case <-time.After(timeout): fmt.Println("Pool parado de força (timeout, podem ficar goroutines penduradas)") } }
Que outros problemas globais existem no código? Como guardar dinheiro — é possível usar float?
/* Uma lista ordenada não decrescente de números inteiros a, um índice index e um número inteiro k. Deve retornar em qualquer ordem k números da lista que sejam os mais próximos em valor do elemento a[index]. a=[2, 3, 5, 7, 11], index=3, k=2 -> [5, 7] a=[4, 12, 15, 15, 24], index=1, k=3 -> [12, 15, 15] a=[2, 3, 5, 7, 11], index=2, k=2 -> [3, 5] ou [5, 7] */
func (r *PayoutRepository) Payout(advertiserID, partnerID string, amount float32) error { advertiser, err := r.find(advertiserID) // adicionar transação if err != nil { return err } partner, err := r.find(partnerID) if err != nil { return err } advertiser.Balance -= amount // proteger SELECT FOR UPDATE partner.Hold -= amount partner.Balance += amount if err := r.save(advertiser); err != nil { return err } if err := r.save(partner); err != nil { return err } r.totalPayouts++ return nil }
Qual é o problema de copiar sql.DB por valor em vez de por ponteiro?
Quanto tempo os logs foram armazenados e quanto tempo os dados foram armazenados no Kafka?
func (r *PayoutRepository) save(p Partner) error { _, err := r.db.Exec( fmt.Sprintf("UPDATE partners SET balance = %s, hold = %s WHERE id = %s", p.Balance, p.Hold, p.ID), ) if err != nil { return err } if err := r.eventPublisher.Publish("BalanceChanged", p); err != nil { return err } return nil }
Dado uma lista ordenada não decrescente de números inteiros a, um índice de elemento index e um número inteiro k. Deve retornar em qualquer ordem k números da lista que sejam os mais próximos em valor ao elemento a[index]. a=[2, 3, 5, 7, 11], index=3, k=2 -> [5, 7] a=[4, 12, 15, 15, 24], index=1, k=3 -> [12, 15, 15] a=[2, 3, 5, 7, 11], index=2, k=2 -> [3, 5] ou [5, 7]
package armazenamento import ( "database/sql" "errors" "fmt" "time" "github.com/company/my-service/internal/event" "github.com/company/my-service/internal/metric" ) type Partner struct { ID string `db:"id" json:"id"` Balance float32 `db:"balance" json:"balance"` Hold float32 `db:"hold" json:"hold"` } type PayoutRepository struct { db sql.DB eventPublisher event.Publisher metricCollector metric.Collector totalPayouts int } func NewPayoutRepository() *PayoutRepository { db, err := sql.Open("postgres", "host=localhost user=postgres password=postgres dbname=affiliate") if err != nil { panic(err) } r := PayoutRepository{ db: db, eventPublisher: event.NewKafkaPublisher("localhost:9092"), metricCollector: metric.NewPrometheusCollector("localhost:9090"), } go func() { for range time.Tick(time.Minute) { _ = r.metricCollector.Send("TotalPayouts", r.totalPayouts) } }() return r } func (r *PayoutRepository) Payout(advertiserID, partnerID string, amount float32) error { advertiser, err := r.find(advertiserID) if err != nil { return err } partner, err := r.find(partnerID) if err != nil { return err } advertiser.Balance -= amount partner.Hold -= amount partner.Balance += amount if err := r.save(advertiser); err != nil { return err } if err := r.save(partner); err != nil { return err } r.totalPayouts++ return nil } func (r *PayoutRepository) find(id string) (Partner, error) { p := Partner{} err := r.db.QueryRow("SELECT * FROM partners WHERE id = " + id).Scan(&p) if err != nil { if err == sql.ErrNoRows { return p, errors.New("partner not found") } return p, err } return p, nil } func (r *PayoutRepository) save(p Partner) error { _, err := r.db.Exec( fmt.Sprintf("UPDATE partners SET balance = %s, hold = %s WHERE id = %s", p.Balance, p.Hold, p.ID), ) if err != nil { return err } if err := r.eventPublisher.Publish("BalanceChanged", p); err != nil { return err } return nil }
Extraia a questão/tarefa da entrevista desta captura de ecrã. Mantenha o idioma original.
func (r *PayoutRepository) Payout(advertiserID, partnerID string, amount float32) error { advertiser, err := r.find(totalPayouts) // adicionar transação if err != nil { return err } partner, err := r.find(partnerID) if err != nil { return err } advertiser.Balance -= amount partner.Hold -= amount partner.Balance += amount if err := r.save(advertiser); err != nil { return err } if err := r.save(partner); err != nil { return err } r.totalPayouts++ return nil } func (r *PayoutRepository) find(id string) (Partner, error) { p := Partner{} err := r.db.QueryRow("SELECT * FROM partners WHERE id = " + id).Scan(&p) // adicionar $1 if err != nil { if err == sql.ErrNoRows { return p, errors.New("parceiro não encontrado") } return p, err } return p, nil }
O que exatamente escrever na mensagem Kafka? Quais campos transmitir aos consumidores?