each.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package v1
  2. import (
  3. "context"
  4. "fmt"
  5. "time"
  6. )
  7. // Count of items per page
  8. var DonatesPerPage = 20
  9. // Pause between requests, Because we can catch:
  10. //
  11. // {"success": false, "message": "Забагато запитів. Спробуйте пізніше."}
  12. var ThrottlingInMilliseconds = 1000
  13. // EachDonate is iterate over all donates and use pagination and throttling.
  14. // Always check returned error and use transaction for preventing to save bad data.
  15. // Count of items per page and throttling value can be changed once in whole package, it's not a constants
  16. //
  17. // Please throw error inside fn function to break whole process, or return just nil. Example:
  18. //
  19. // isFound := false
  20. // client.EachDonate(ctx, func(donate *v1.ResponseDonatesContent) error {
  21. // if donate.PubID == "12345" {
  22. // fmt.Printf("Donate: %#v\n", donate)
  23. // isFound = true
  24. // }
  25. // if isFound {
  26. // return fmt.Errorf("break")
  27. // }
  28. // return nil
  29. // })
  30. func (c *Client) EachDonate(ctx context.Context, fn func(donate *ResponseDonatesContent) error) error {
  31. var resp *ResponseDonates
  32. var err error
  33. p := int64(0)
  34. for {
  35. resp, err = c.Donates(ctx, p, int64(DonatesPerPage))
  36. if err != nil {
  37. return err
  38. }
  39. if !resp.Success {
  40. return fmt.Errorf("%s", resp.Message)
  41. }
  42. if len(resp.Content) > 0 {
  43. for _, donate := range resp.Content {
  44. err = fn(&donate)
  45. if err != nil {
  46. return err
  47. }
  48. select {
  49. case <-ctx.Done():
  50. return fmt.Errorf("context canceled")
  51. default:
  52. }
  53. }
  54. }
  55. p++
  56. if err != nil {
  57. break
  58. }
  59. if p >= resp.Pages {
  60. break
  61. }
  62. if resp.Page >= resp.Pages {
  63. break
  64. }
  65. select {
  66. case <-ctx.Done():
  67. return fmt.Errorf("context canceled")
  68. default:
  69. }
  70. // Throttling
  71. time.Sleep(time.Duration(ThrottlingInMilliseconds) * time.Millisecond)
  72. }
  73. return err
  74. }