// add $1
Golang
If you were to write unit tests for your code, which ones would you write? What corner cases would you check?
Where to get the event ID for idempotency and where to generate it?
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 }
How to understand at the SQL level that such a key of idempotency already exists? How to use ON CONFLICT?
Where did you store the logs, which logging package did you use in the code, and how did the logs get from stdout to Elasticsearch?
Tell me about the project/vacancy: technology stack, team tasks
What other global issues exist in the code? How to store money — can float be used?
If a transaction is not committed, what happens to the ID in the outbox?
func (r *PayoutRepository) Payout(advertiserID, partnerID string, amount float32) error { advertiser, err := r.find(advertiserID) // add transaction if err != nil { return err } partner, err := r.find(partnerID) if err != nil { return err } advertiser.Balance -= amount // protect 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 }
What is the problem with copying sql.DB by value instead of by pointer?
How long were logs stored and how long was data stored in Kafka?
func (p *Pool) Stop() { p.mu.Unlock() // Now it is safe to close the channel close(p.tasks) // signal to workers: no new tasks, read remaining p.wg.Wait() // wait for all goroutines to finish p.cancel() // cancel the context just in case fmt.Println("Pool stopped.") } // ForceStop forcibly stops all workers without waiting for task completion. // Workers will be interrupted immediately via context. func (p *Pool) ForceStop(timeout time.Duration) { fmt.Printf("Force stopping pool (timeout: %v)...\n", timeout) // Lock adding new tasks p.mu.Lock() p.isOpen = false p.mu.Unlock() // Close the channel so workers do not take new tasks close(p.tasks) // Cancel the context – this will interrupt all running tasks p.cancel() // Give a limited time to finish done := make(chan struct{}) go func() { p.wg.Wait() close(done) }() select { case <-done: fmt.Println("Pool force stopped (all workers finished)") case <-time.After(timeout): fmt.Println("Pool force stopped (timeout, some goroutines may remain hanging)") } }
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 }
Extract the interview question/task from this screenshot. Keep the original language.
func (r *PayoutRepository) Payout(advertiserID, partnerID string, amount float32) error { advertiser, err := r.find(totalPayouts) // добавить транзакцию 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) // добавить $1 if err != nil { if err == sql.ErrNoRows { return p, errors.New("partner not found") } return p, err } return p, nil }
/* Given a sorted list of integers a in non-decreasing order, an index element index, and an integer k. Return any order of k numbers from the list that are closest in value to 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] or [5, 7] */
What exactly to write in the Kafka message? Which fields to pass to consumers?
What does ld, rd := 1<<62, 1<<62 mean in the context of an algorithm?
package storage 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 }