Skip to content

Commit

Permalink
add retry
Browse files Browse the repository at this point in the history
  • Loading branch information
nukokusa committed Mar 29, 2023
1 parent 2981f8e commit 227e0d7
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 24 deletions.
106 changes: 85 additions & 21 deletions calendar.go
Expand Up @@ -2,12 +2,16 @@ package koyomi

import (
"context"
"log"
"net/http"
"sort"
"time"

"github.com/pkg/errors"
"github.com/shogo82148/go-retry"
"github.com/tkuchiki/parsetime"
"google.golang.org/api/calendar/v3"
"google.golang.org/api/googleapi"
"google.golang.org/api/option"
)

Expand Down Expand Up @@ -62,37 +66,56 @@ type CalendarService interface {
}

type calendarService struct {
cs *calendar.Service
cs *calendar.Service
policy retry.Policy
}

func newCalendarService(ctx context.Context, credentialPath string) (CalendarService, error) {
cs, err := calendar.NewService(ctx, option.WithCredentialsFile(credentialPath))
if err != nil {
return nil, errors.Wrap(err, "error calendar.NewService")
}
policy := retry.Policy{
MinDelay: time.Second,
MaxDelay: 100 * time.Second,
MaxCount: 10,
}
return &calendarService{
cs: cs,
cs: cs,
policy: policy,
}, nil
}

func (s *calendarService) List(ctx context.Context, calendarID string, startTime, endTime time.Time) ([]*Event, error) {
pageToken := ""
evs := []*calendar.Event{}
req := s.cs.Events.List(calendarID).
TimeMin(startTime.Format(time.RFC3339)).
TimeMax(endTime.Format(time.RFC3339)).
SingleEvents(true)

pageToken := ""
for {
es, err := s.cs.Events.List(calendarID).
TimeMin(startTime.Format(time.RFC3339)).
TimeMax(endTime.Format(time.RFC3339)).
SingleEvents(true).
PageToken(pageToken).
Context(ctx).Do()
if err != nil {
retrier := s.policy.Start(ctx)
var resp *calendar.Events
for retrier.Continue() {
var err error
resp, err = req.PageToken(pageToken).Context(ctx).Do()
if err == nil {
break
}
if apiError, ok := err.(*googleapi.Error); ok {
if apiError.Code == http.StatusTooManyRequests {
log.Printf("[WARN] reached to TooManyRequests: CalendarID=%s", calendarID)
continue
}
}
return nil, errors.Wrap(err, "error Events.List")
}
evs = append(evs, es.Items...)
if es.NextPageToken == "" {
evs = append(evs, resp.Items...)
if resp.NextPageToken == "" {
break
}
pageToken = es.NextPageToken
pageToken = resp.NextPageToken
}

result := make([]*Event, 0, len(evs))
Expand Down Expand Up @@ -121,12 +144,26 @@ func (s *calendarService) Insert(ctx context.Context, calendarID string, event *
DateTime: event.EndTime.Format(time.RFC3339),
},
}
ev, err := s.cs.Events.Insert(calendarID, ev).Context(ctx).Do()
if err != nil {
req := s.cs.Events.Insert(calendarID, ev)

retrier := s.policy.Start(ctx)
var resp *calendar.Event
for retrier.Continue() {
var err error
resp, err = req.Context(ctx).Do()
if err == nil {
break
}
if apiError, ok := err.(*googleapi.Error); ok {
if apiError.Code == http.StatusTooManyRequests {
log.Printf("[WARN] reached to Too Many Requests: calendar_id=%s", calendarID)
continue
}
}
return nil, errors.Wrap(err, "error Events.Insert")
}

result, err := NewEvent(ev)
result, err := NewEvent(resp)
if err != nil {
return nil, errors.Wrap(err, "error NewEvent")
}
Expand All @@ -145,21 +182,48 @@ func (s *calendarService) Patch(ctx context.Context, calendarID string, event *E
if !event.EndTime.IsZero() {
ev.End.DateTime = event.EndTime.Format(time.RFC3339)
}
ev, err := s.cs.Events.Patch(calendarID, ev.Id, ev).Context(ctx).Do()
if err != nil {
return nil, errors.Wrap(err, "error Events.Patch")
req := s.cs.Events.Patch(calendarID, ev.Id, ev)

retrier := s.policy.Start(ctx)
var resp *calendar.Event
for retrier.Continue() {
var err error
resp, err = req.Context(ctx).Do()
if err == nil {
break
}
if apiError, ok := err.(*googleapi.Error); ok {
if apiError.Code == http.StatusTooManyRequests {
log.Printf("[WARN] reached to Too Many Requests: calendar_id=%s", calendarID)
continue
}
}
return nil, errors.Wrap(err, "error Events.Insert")
}

result, err := NewEvent(ev)
result, err := NewEvent(resp)
if err != nil {
return nil, errors.Wrap(err, "error NewEvent")
}
return result, nil
}

func (s *calendarService) Delete(ctx context.Context, calendarID, eventID string) error {
if err := s.cs.Events.Delete(calendarID, eventID).Context(ctx).Do(); err != nil {
req := s.cs.Events.Delete(calendarID, eventID)
retrier := s.policy.Start(ctx)
for retrier.Continue() {
err := req.Context(ctx).Do()
if err == nil {
break
}
if apiError, ok := err.(*googleapi.Error); ok {
if apiError.Code == http.StatusTooManyRequests {
log.Printf("[WARN] reached to Too Many Requests: calendar_id=%s", calendarID)
continue
}
}
return errors.Wrap(err, "error Events.Delete")
}

return nil
}
2 changes: 1 addition & 1 deletion create.go
Expand Up @@ -49,7 +49,7 @@ func (k *Koyomi) Create(ctx context.Context, opt *CreateOption) error {
return errors.Wrap(err, "error Insert")
}

log.Printf("[DEBUG] inserted event: CalendarID=%s, ID=%s", opt.CalendarID, event.ID)
log.Printf("[DEBUG] inserted event: calendar_id=%s, id=%s", opt.CalendarID, event.ID)

if err := json.NewEncoder(k.stdout).Encode(event); err != nil {
return errors.Wrap(err, "error Encode")
Expand Down
2 changes: 1 addition & 1 deletion delete.go
Expand Up @@ -17,7 +17,7 @@ func (k *Koyomi) Delete(ctx context.Context, opt *DeleteOption) error {
return errors.Wrap(err, "error Delete")
}

log.Printf("[DEBUG] deleted event: CalendarID=%s, ID=%s", opt.CalendarID, opt.ID)
log.Printf("[DEBUG] deleted event: calendar_id=%s, id=%s", opt.CalendarID, opt.ID)

return nil
}
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -8,6 +8,7 @@ require (
github.com/google/go-cmp v0.5.9
github.com/hashicorp/logutils v1.0.0
github.com/pkg/errors v0.9.1
github.com/shogo82148/go-retry v1.1.1
github.com/tkuchiki/parsetime v0.3.0
google.golang.org/api v0.114.0
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Expand Up @@ -67,6 +67,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/shogo82148/go-retry v1.1.1 h1:BfUEVHTNDSjYxoRPC+c/ht5Sy6qdwl+0kFhhubeh4Fo=
github.com/shogo82148/go-retry v1.1.1/go.mod h1:TPSFDcc2rlx2D/yfhi8BBOlsHhVBjjJoMvxG7iFHUbI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand Down
2 changes: 1 addition & 1 deletion update.go
Expand Up @@ -54,7 +54,7 @@ func (k *Koyomi) Update(ctx context.Context, opt *UpdateOption) error {
return errors.Wrap(err, "error Patch")
}

log.Printf("[DEBUG] updated event: CalendarID=%s, ID=%s", opt.CalendarID, event.ID)
log.Printf("[DEBUG] updated event: calendar_id=%s, id=%s", opt.CalendarID, event.ID)

if err := json.NewEncoder(k.stdout).Encode(event); err != nil {
return errors.Wrap(err, "error Encode")
Expand Down

0 comments on commit 227e0d7

Please sign in to comment.