X-Git-Url: https://git.octo.it/?p=kraftakt.git;a=blobdiff_plain;f=fitbit%2Ffitbit.go;h=bdfc3ddc9b8068f40dc9e27d397c96297be898a2;hp=6f15027dd08e80768784f2351f48c780272df547;hb=6e353fc58f08533be15182536e7b0c5099c098b8;hpb=2841c9d9e955da6cc3c5962e002538700e8ffbbb diff --git a/fitbit/fitbit.go b/fitbit/fitbit.go index 6f15027..bdfc3dd 100644 --- a/fitbit/fitbit.go +++ b/fitbit/fitbit.go @@ -123,19 +123,40 @@ type Client struct { } func NewClient(ctx context.Context, fitbitUserID string, u *app.User) (*Client, error) { - tok, err := u.Token(ctx, "Fitbit") + if fitbitUserID == "" { + fitbitUserID = "-" + } + + storedToken, err := u.Token(ctx, "Fitbit") if err != nil { return nil, err } - if fitbitUserID == "" { - fitbitUserID = "-" + // The oauth2 package will refresh the token when it is valid for less + // than 10 seconds. To avoid a race with later calls (which would + // refresh the token but the new RefreshToken wouldn't make it back + // into datastore), we refresh earlier than that. The Fitbit tokens are + // quite long-lived (six hours?); the additional load this puts on the + // backends is negligible. + if storedToken.Expiry.Round(0).Add(-5 * time.Minute).Before(time.Now()) { + storedToken.Expiry = time.Now() + } + + refreshedToken, err := oauth2Config.TokenSource(ctx, storedToken).Token() + if err != nil { + return nil, err + } + + if refreshedToken.RefreshToken != storedToken.RefreshToken { + if err := u.SetToken(ctx, "Fitbit", refreshedToken); err != nil { + return nil, err + } } return &Client{ fitbitUserID: fitbitUserID, appUser: u, - client: oauth2Config.Client(ctx, tok), + client: oauth2Config.Client(ctx, refreshedToken), }, nil }