1- using System . Runtime . CompilerServices ;
21using Microsoft . Extensions . Logging ;
32using Microsoft . Extensions . Logging . Abstractions ;
43
5- [ assembly: InternalsVisibleTo ( "DynamicProxyGenAssembly2" ) ]
6-
74namespace Ydb . Sdk . Auth ;
85
96public class TokenManagerCredentialsProvider : ICredentialsProvider
@@ -13,7 +10,7 @@ public class TokenManagerCredentialsProvider : ICredentialsProvider
1310
1411 private ILogger < TokenManagerCredentialsProvider > Logger { get ; }
1512
16- private volatile IHolderState _holderState ;
13+ private volatile ITokenState _tokenState ;
1714
1815 public TokenManagerCredentialsProvider (
1916 IAuthClient authClient ,
@@ -22,8 +19,8 @@ public TokenManagerCredentialsProvider(
2219 {
2320 _clock = new SystemClock ( ) ;
2421 _authClient = authClient ;
25- _holderState = new SyncState ( this ) ;
26- _holderState . Init ( ) ;
22+ _tokenState = new SyncState ( this ) ;
23+ _tokenState . Init ( ) ;
2724
2825 loggerFactory ??= new NullLoggerFactory ( ) ;
2926 Logger = loggerFactory . CreateLogger < TokenManagerCredentialsProvider > ( ) ;
@@ -35,32 +32,32 @@ internal TokenManagerCredentialsProvider(IAuthClient authClient, IClock clock) :
3532 }
3633
3734 public async ValueTask < string > GetAuthInfoAsync ( ) =>
38- ( await _holderState . Validate ( _clock . UtcNow ) ) . TokenResponse . Token ;
35+ ( await _tokenState . Validate ( _clock . UtcNow ) ) . TokenResponse . Token ;
3936
4037 private ValueTask < TokenResponse > FetchToken ( ) => _authClient . FetchToken ( ) ;
4138
42- private IHolderState UpdateState ( IHolderState current , IHolderState next )
39+ private ITokenState UpdateState ( ITokenState current , ITokenState next )
4340 {
44- if ( Interlocked . CompareExchange ( ref _holderState , next , current ) == current )
41+ if ( Interlocked . CompareExchange ( ref _tokenState , next , current ) == current )
4542 {
4643 next . Init ( ) ;
4744 }
4845
49- return _holderState ;
46+ return _tokenState ;
5047 }
5148
52- private interface IHolderState
49+ private interface ITokenState
5350 {
5451 TokenResponse TokenResponse { get ; }
5552
56- ValueTask < IHolderState > Validate ( DateTime now ) ;
53+ ValueTask < ITokenState > Validate ( DateTime now ) ;
5754
5855 void Init ( )
5956 {
6057 }
6158 }
6259
63- private class ActiveState : IHolderState
60+ private class ActiveState : ITokenState
6461 {
6562 private readonly TokenManagerCredentialsProvider _tokenManagerCredentialsProvider ;
6663
@@ -72,25 +69,31 @@ public ActiveState(TokenResponse tokenResponse, TokenManagerCredentialsProvider
7269
7370 public TokenResponse TokenResponse { get ; }
7471
75- public async ValueTask < IHolderState > Validate ( DateTime now )
72+ public async ValueTask < ITokenState > Validate ( DateTime now )
7673 {
77- if ( now >= TokenResponse . ExpiresAt )
74+ if ( now < TokenResponse . ExpiredAt )
7875 {
79- return await _tokenManagerCredentialsProvider
80- . UpdateState ( this , new SyncState ( _tokenManagerCredentialsProvider ) )
81- . Validate ( now ) ;
76+ return now >= TokenResponse . RefreshAt
77+ ? _tokenManagerCredentialsProvider . UpdateState (
78+ this ,
79+ new BackgroundState ( TokenResponse , _tokenManagerCredentialsProvider )
80+ )
81+ : this ;
8282 }
8383
84- return now >= TokenResponse . RefreshAt
85- ? _tokenManagerCredentialsProvider . UpdateState (
86- this ,
87- new BackgroundState ( TokenResponse , _tokenManagerCredentialsProvider )
88- )
89- : this ;
84+ _tokenManagerCredentialsProvider . Logger . LogWarning (
85+ "Token has expired. ExpiredAt: {ExpiredAt}, CurrentTime: {CurrentTime}. " +
86+ "Switching to synchronous state to fetch a new token" ,
87+ TokenResponse . ExpiredAt , now
88+ ) ;
89+
90+ return await _tokenManagerCredentialsProvider
91+ . UpdateState ( this , new SyncState ( _tokenManagerCredentialsProvider ) )
92+ . Validate ( now ) ;
9093 }
9194 }
9295
93- private class SyncState : IHolderState
96+ private class SyncState : ITokenState
9497 {
9598 private readonly TokenManagerCredentialsProvider _tokenManagerCredentialsProvider ;
9699
@@ -104,14 +107,19 @@ public SyncState(TokenManagerCredentialsProvider tokenManagerCredentialsProvider
104107 public TokenResponse TokenResponse =>
105108 throw new InvalidOperationException ( "Get token for unfinished sync state" ) ;
106109
107- public async ValueTask < IHolderState > Validate ( DateTime now )
110+ public async ValueTask < ITokenState > Validate ( DateTime now )
108111 {
109112 try
110113 {
111- var tokenHolder = await _fetchTokenTask ;
114+ var tokenResponse = await _fetchTokenTask ;
115+
116+ _tokenManagerCredentialsProvider . Logger . LogDebug (
117+ "Successfully fetched token at {Timestamp}. ExpiredAt: {ExpiredAt}, RefreshAt: {RefreshAt}" ,
118+ DateTime . Now , tokenResponse . ExpiredAt , tokenResponse . RefreshAt
119+ ) ;
112120
113121 return _tokenManagerCredentialsProvider . UpdateState ( this ,
114- new ActiveState ( tokenHolder , _tokenManagerCredentialsProvider ) ) ;
122+ new ActiveState ( tokenResponse , _tokenManagerCredentialsProvider ) ) ;
115123 }
116124 catch ( Exception e )
117125 {
@@ -125,7 +133,7 @@ public async ValueTask<IHolderState> Validate(DateTime now)
125133 public void Init ( ) => _fetchTokenTask = _tokenManagerCredentialsProvider . FetchToken ( ) . AsTask ( ) ;
126134 }
127135
128- private class BackgroundState : IHolderState
136+ private class BackgroundState : ITokenState
129137 {
130138 private readonly TokenManagerCredentialsProvider _tokenManagerCredentialsProvider ;
131139
@@ -140,11 +148,16 @@ public BackgroundState(TokenResponse tokenResponse,
140148
141149 public TokenResponse TokenResponse { get ; }
142150
143- public async ValueTask < IHolderState > Validate ( DateTime now )
151+ public async ValueTask < ITokenState > Validate ( DateTime now )
144152 {
145153 if ( _fetchTokenTask . IsCanceled || _fetchTokenTask . IsFaulted )
146154 {
147- return now > TokenResponse . ExpiresAt
155+ _tokenManagerCredentialsProvider . Logger . LogWarning (
156+ "Fetching token task failed. Status: {Status}, Retrying login..." ,
157+ _fetchTokenTask . IsCanceled ? "Canceled" : "Faulted"
158+ ) ;
159+
160+ return now >= TokenResponse . ExpiredAt
148161 ? _tokenManagerCredentialsProvider
149162 . UpdateState ( this , new SyncState ( _tokenManagerCredentialsProvider ) )
150163 : _tokenManagerCredentialsProvider
@@ -157,17 +170,22 @@ public async ValueTask<IHolderState> Validate(DateTime now)
157170 . UpdateState ( this , new ActiveState ( await _fetchTokenTask , _tokenManagerCredentialsProvider ) ) ;
158171 }
159172
160- if ( now < TokenResponse . ExpiresAt )
173+ if ( now < TokenResponse . ExpiredAt )
161174 {
162175 return this ;
163176 }
164177
165178 try
166179 {
167- var tokenHolder = await _fetchTokenTask ;
180+ var tokenResponse = await _fetchTokenTask ;
181+
182+ _tokenManagerCredentialsProvider . Logger . LogDebug (
183+ "Successfully fetched token. ExpiredAt: {ExpiredAt}, RefreshAt: {RefreshAt}" ,
184+ tokenResponse . ExpiredAt , tokenResponse . RefreshAt
185+ ) ;
168186
169187 return _tokenManagerCredentialsProvider . UpdateState ( this ,
170- new ActiveState ( tokenHolder , _tokenManagerCredentialsProvider ) ) ;
188+ new ActiveState ( tokenResponse , _tokenManagerCredentialsProvider ) ) ;
171189 }
172190 catch ( Exception e )
173191 {
@@ -181,7 +199,7 @@ public async ValueTask<IHolderState> Validate(DateTime now)
181199 public void Init ( ) => _fetchTokenTask = _tokenManagerCredentialsProvider . FetchToken ( ) . AsTask ( ) ;
182200 }
183201
184- private class ErrorState : IHolderState
202+ private class ErrorState : ITokenState
185203 {
186204 private readonly Exception _exception ;
187205 private readonly TokenManagerCredentialsProvider _managerCredentialsProvider ;
@@ -194,7 +212,7 @@ public ErrorState(Exception exception, TokenManagerCredentialsProvider managerCr
194212
195213 public TokenResponse TokenResponse => throw _exception ;
196214
197- public ValueTask < IHolderState > Validate ( DateTime now ) => _managerCredentialsProvider
215+ public ValueTask < ITokenState > Validate ( DateTime now ) => _managerCredentialsProvider
198216 . UpdateState ( this , new SyncState ( _managerCredentialsProvider ) )
199217 . Validate ( now ) ;
200218 }
@@ -204,21 +222,21 @@ public class TokenResponse
204222{
205223 private const double RefreshInterval = 0.5 ;
206224
207- public TokenResponse ( string token , DateTime expiresAt , DateTime ? refreshAt = null )
225+ public TokenResponse ( string token , DateTime expiredAt , DateTime ? refreshAt = null )
208226 {
209227 var now = DateTime . UtcNow ;
210228
211229 Token = token ;
212- ExpiresAt = expiresAt . ToUniversalTime ( ) ;
213- RefreshAt = refreshAt ? . ToUniversalTime ( ) ?? now + ( ExpiresAt - now ) * RefreshInterval ;
230+ ExpiredAt = expiredAt . ToUniversalTime ( ) ;
231+ RefreshAt = refreshAt ? . ToUniversalTime ( ) ?? now + ( ExpiredAt - now ) * RefreshInterval ;
214232 }
215233
216- internal string Token { get ; }
217- internal DateTime ExpiresAt { get ; }
218- internal DateTime RefreshAt { get ; }
234+ public string Token { get ; }
235+ public DateTime ExpiredAt { get ; }
236+ public DateTime RefreshAt { get ; }
219237}
220238
221- internal interface IClock
239+ public interface IClock
222240{
223241 DateTime UtcNow { get ; }
224242}
0 commit comments