// ավելացնել $1
Golang
Եթե դու ինքներդ գրումիր միավորական թեստեր քո կոդի համար, որոնք կգրեիր? Որոնք կպարզեիր որպես անկյունային դեպքեր?
Որտեղից ստանալ իրադարձության ID-ը իդեմպոտենցիայի համար և որտեղ այն ստեղծել?
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 }
Ինչպե՞ս հասկանալ SQL մակարդակով, որ արդեն կա այդպիսի իդեմպոտենցության բանալի: Ինչպե՞ս օգտագործել ON CONFLICT-ը։
Որտե՞ղ եք պահել լոգերը, որ լոգավորման փաթեթ եք օգտագործել կոդում և ինչպես լոգերը անցան stdout-ից Elasticsearch:
Պատմիր նախագծի/վազքի մասին՝ տեխնոլոգիական շերտ, թիմի առաջադրանքներ
Ի՞նչ այլ գլոբալ խնդիրներ կան կոդում: Ինչպե՞ս պահել գումարը — կարելի է օգտագործել float:
Եթե գործարքը չհաստատվի, ինչ կլինի outbox-ում գտնվող ID- ի հետ?
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 // պաշտպանել 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 }
Ի՞նչ է խնդիրը sql.DB-ի արժեքով պատճենելիս, ոչ թե ցուցիչով։
Որքա՞ն ժամանակ են պահվել լոգերը և որքան ժամանակ են պահվել տվյալները Kafka-ում։
func (p *Pool) Stop() { p.mu.Unlock() // Այժմ անվտանգ է փակել ալիքը close(p.tasks) // ազդանշան աշխատողներին՝ նոր առաջադրանքներ չեն լինի, կարդացեք մնացորդը p.wg.Wait() // սպասում ենք բոլոր գորուտինների ավարտին p.cancel() // անհրաժեշտության դեպքում չեղյալ հայտարարում ենք կոնտեքստը fmt.Println("Pool կանգնեց.") } // ForceStop ուժեղորեն կանգնեցնում է բոլոր աշխատողներին՝ սպասելու Tasks-ի ավարտին չպահանջելով: // Աշխատողները անմիջապես կկտրվեն կոնտեքստի միջոցով: func (p *Pool) ForceStop(timeout time.Duration) { fmt.Printf("Համառորեն կանգնեցնելու պուլը (timeout: %v)...\n", timeout) // Բլոկավորում է նոր առաջադրանքների ավելացումը p.mu.Lock() p.isOpen = false p.mu.Unlock() // Ալիքը փակվում է, որպեսզի աշխատողներն այլևս չստանան նոր առաջադրանքներ close(p.tasks) // Կոնտեքստը չեղյալ է հայտարարվում – դա կկտրի բոլոր ընթացիկ առաջադրանքները p.cancel() // Մ محدود ժամանակ է տրվում ավարտին հասցնելու համար done := make(chan struct{}) go func() { p.wg.Wait() close(done) }() select { case <-done: fmt.Println("Պուլը ուժեղորեն կանգնեցվեց (բոլոր աշխատողները ավարտվեցին)") case <-time.After(timeout): fmt.Println("Պուլը ուժեղորեն կանգնեցվեց (timeout, կարող են մնալ կախված goroutine-ներ)") } }
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 }
Ներկայացրեք հարցազրույցի հարցը/գործառույթը այս սքրինշոթից: Պահպանեք բնօրինակի լեզուն։
func (r *PayoutRepository) Payout(advertiserID, partnerID string, amount float32) error { advertiser, err := r.find(totalPayouts) // գործարք ավելացնել եթե սխալ != ոչ { վերադարձնել սխալ } գործընկեր, սխալ := r.find(partnerID) եթե սխալ != ոչ { վերադարձնել սխալ } գովազդատու, Բալանս -= գումար գործընկեր.Hold -= գումար գործընկեր.Бalance += գումար եթե սխալ := r.save(գովազդատու); սխալ != ոչ { վերադարձնել սխալ } եթե սխալ := r.save(գործընկեր); սխալ != ոչ { վերադարձնել սխալ } r.totalPayouts++ վերադարձնել ոչ } ֆունկցիա (r *PayoutRepository) find(id string) (Partner, սխալ) { p := Partner{} սխալ := r.db.QueryRow("SELECT * FROM partners WHERE id = " + id).Scan(&p) // $1 ավելացնել եթե սխալ != ոչ { եթե սխալ == sql.ErrNoRows { վերադարձնել p, errors.New("գործընկերը չի գտնվել") } վերադարձնել p, սխալ } վերադարձնել p, ոչ }
/* Տեղադրված է աճող կարգով ամբողջ թվերի ցանկ a, ցուցիչ index և ամբողջ թիվ k: Պետք է ցանկացած կարգով վերադարձնել ցանկից k թիվ, որոնք ամենամոտ են 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] կամ [5, 7] */
Ինչպես պետք է գրել Kafka հաղորդագրության մեջ: Որ ֆիլդերը փոխանցել սպառողներին?
Ի՞նչ են ld, rd := 1<<62, 1<<62 ալգորիթմի համատեքստում։
կազմաձև պահեստավորում միավորել ( "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 }