// aggiungi $1
Golang
Se scrivessi test unitari per il tuo codice, quali scriveresti? Quali corner cases controlleresti?
Da dove ottenere l'ID dell'evento per l'idempotenza e dove generarlo?
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 }
Come capire a livello SQL se esiste già una chiave di idempotenza? Come usare ON CONFLICT?
Dove hai archiviato i log, quale pacchetto di logging hai usato nel codice e come sono passati i log da stdout a Elasticsearch?
Parla del progetto/offerta di lavoro: stack tecnologico, compiti del team
Cosa succede all'ID in outbox se la transazione non viene confermata?
func (r *PayoutRepository) Payout(advertiserID, partnerID string, amount float32) error { advertiser, err := r.find(advertiserID) // aggiungere transazione if err != nil { return err } partner, err := r.find(partnerID) if err != nil { return err } advertiser.Balance -= amount // proteggere 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 }
Quali altri problemi globali ci sono nel codice? Come conservare i soldi — si può usare float?
Qual è il problema di copiare sql.DB per valore invece che per puntatore?
func (p *Pool) Stop() { p.mu.Unlock() // Ora è sicuro chiudere il canale close(p.tasks) // segnale ai worker: nessun nuovo compito, leggere il resto p.wg.Wait() // aspettiamo che tutte le goroutine finiscano p.cancel() // annulliamo il contesto per sicurezza fmt.Println("Pool fermato.") } // ForceStop forza l'arresto di tutti i worker senza aspettare che finiscano i compiti. // I worker saranno interrotti immediatamente tramite il contesto. func (p *Pool) ForceStop(timeout time.Duration) { fmt.Printf("Arresto forzato del pool (timeout: %v)...\n", timeout) // Blocca l'aggiunta di nuovi compiti p.mu.Lock() p.isOpen = false p.mu.Unlock() // Chiude il canale affinché i worker non prendano nuovi compiti close(p.tasks) // Annulla il contesto – questo interromperà tutti i compiti in corso p.cancel() // Dai un tempo limitato per terminare done := make(chan struct{}) go func() { p.wg.Wait() close(done) }() select { case <-done: fmt.Println("Pool forzatamente fermato (tutti i worker sono terminati)") case <-time.After(timeout): fmt.Println("Pool forzatamente fermato (timeout, potrebbero rimanere goroutine in sospeso)") } }
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 }
Quanto tempo sono stati conservati i log e quanto tempo sono stati conservati i dati in Kafka?
func (r *PayoutRepository) Payout(advertiserID, partnerID string, amount float32) error { advertiser, err := r.find(totalPayouts) // aggiungi una transazione 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) // aggiungi $1 if err != nil { if err == sql.ErrNoRows { return p, errors.New("partner non trovato") } return p, err } return p, nil }
Estrai la domanda/compito dell'intervista da questa schermata. Mantieni la lingua originale.
/* Una lista ordinata in modo non decrescente di numeri interi a, un indice index e un numero intero k. Devi restituire in qualsiasi ordine k numeri dalla lista che siano i più vicini in valore all'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] o [5, 7] */
Cosa sono ld, rd := 1<<62, 1<<62 nel contesto dell'algoritmo?
Cosa scrivere esattamente nel messaggio Kafka? Quali campi trasmettere ai consumatori?
pacchetto archiviazione 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 }