@@ -18,84 +18,80 @@ type Client struct {
1818 secretId string
1919 secretKey string
2020
21- token * Token
22- nextRefresh time.Time
23-
24- m * sync.RWMutex
25- stopChan chan struct {}
21+ m * sync.RWMutex
22+ token * Token
2623}
2724
2825type Transport struct {
2926 rt http.RoundTripper
3027 cli * Client
3128}
3229
33- // refreshTokenIfNeeded refreshes the token if refresh time has passed
34- func (c * Client ) refreshTokenIfNeeded (ctx context.Context ) error {
35- c .m .Lock ()
36- defer c .m .Unlock ()
37-
38- if time .Now ().Before (c .nextRefresh ) {
39- return nil
40- }
41-
42- newToken , err := c .refreshToken (ctx , c .token .Refresh )
43- if err != nil {
44- return err
45- }
46- c .updateToken (newToken )
47- return nil
48- }
49-
50- // updateToken updates the client token and sets the refresh time to half the
51- // access token lifetime.
52- func (c * Client ) updateToken (t * Token ) {
53- c .token = t
54- c .nextRefresh = time .Now ().Add (time .Duration (t .AccessExpires / 2 ) * time .Second )
55- }
56-
5730// StartTokenHandler handles token refreshes in the background
5831func (c * Client ) StartTokenHandler (ctx context.Context ) error {
5932 // Initialize the first token
6033 token , err := c .newToken (ctx )
6134 if err != nil {
62- return errors .New ("failed to get initial token: " + err .Error ())
35+ return errors .New ("getting initial token: " + err .Error ())
6336 }
64-
6537 c .m .Lock ()
66- c .updateToken ( token )
38+ c .token = token
6739 c .m .Unlock ()
6840
69- go c .tokenRefreshLoop (ctx )
41+ go c .tokenHandler (ctx )
7042 return nil
7143}
7244
73- func (c * Client ) tokenRefreshLoop (ctx context.Context ) {
45+ // tokenHandler gets a new token using the refresh token and a new pair when the
46+ // refresh token expires.
47+ func (c * Client ) tokenHandler (ctx context.Context ) {
48+ newTokenTimer := time .NewTimer (0 ) // Start immediately
49+ refreshTokenTimer := time .NewTimer (0 ) // Start immediately
50+ defer func () {
51+ newTokenTimer .Stop ()
52+ refreshTokenTimer .Stop ()
53+ }()
54+
55+ resetTimer := func (timer * time.Timer , expiryTime time.Time ) {
56+ if ! timer .Stop () {
57+ <- timer .C
58+ }
59+ timer .Reset (time .Until (expiryTime ))
60+ }
61+
7462 for {
7563 c .m .RLock ()
76- refreshTime := c .nextRefresh
64+ newTokenExpiry := c .token .accessExpires (2 )
65+ refreshTokenExpiry := c .token .refreshExpires (2 )
7766 c .m .RUnlock ()
7867
79- timeToWait := time .Until (refreshTime )
80- if timeToWait < 0 {
81- timeToWait = 0
82- }
68+ resetTimer (newTokenTimer , newTokenExpiry )
69+ resetTimer (refreshTokenTimer , refreshTokenExpiry )
8370
8471 select {
85- case <- c .stopChan :
86- return
87- case <- time .After (timeToWait ):
88- if err := c .refreshTokenIfNeeded (ctx ); err != nil {
89- panic (fmt .Sprintf ("failed to refresh token: %s" , err ))
90- }
9172 case <- ctx .Done ():
9273 return
74+ case <- newTokenTimer .C :
75+ if token , err := c .newToken (ctx ); err != nil {
76+ panic (fmt .Sprintf ("getting new token: %s" , err ))
77+ } else {
78+ c .updateToken (token )
79+ }
80+ case <- refreshTokenTimer .C :
81+ if token , err := c .refreshToken (ctx ); err != nil {
82+ panic (fmt .Sprintf ("refreshing token: %s" , err ))
83+ } else {
84+ c .updateToken (token )
85+ }
9386 }
9487 }
9588}
9689
97- func (c * Client ) StopTokenHandler () {
98- close (c .stopChan )
90+ // updateToken updates the client's token
91+ func (c * Client ) updateToken (t * Token ) {
92+ c .m .Lock ()
93+ defer c .m .Unlock ()
94+ c .token = t
9995}
10096
10197func (t Transport ) RoundTrip (req * http.Request ) (* http.Response , error ) {
@@ -122,8 +118,7 @@ func NewClient(secretId, secretKey string) (*Client, error) {
122118 secretId : secretId ,
123119 secretKey : secretKey ,
124120
125- m : & sync.RWMutex {},
126- stopChan : make (chan struct {}),
121+ m : & sync.RWMutex {},
127122 }
128123
129124 // Add transport to handle headers, host and path for all requests
0 commit comments