@@ -6,6 +6,7 @@ namespace PowerSync.Common.Client.Sync.Stream;
6
6
using System . Text ;
7
7
using System . Threading ;
8
8
using System . Threading . Tasks ;
9
+ using System . Text . RegularExpressions ;
9
10
10
11
using Newtonsoft . Json ;
11
12
using Newtonsoft . Json . Linq ;
@@ -29,7 +30,6 @@ public class RequestDetails
29
30
30
31
public class Remote
31
32
{
32
- private static int REFRESH_CREDENTIALS_SAFETY_PERIOD_MS = 30_000 ;
33
33
private readonly HttpClient httpClient ;
34
34
protected IPowerSyncBackendConnector connector ;
35
35
@@ -41,18 +41,48 @@ public Remote(IPowerSyncBackendConnector connector)
41
41
this . connector = connector ;
42
42
}
43
43
44
+ /// <summary>
45
+ /// Get credentials currently cached, or fetch new credentials if none are available.
46
+ /// These credentials may have expired already.
47
+ /// </summary>
44
48
public async Task < PowerSyncCredentials ? > GetCredentials ( )
45
49
{
46
- if ( credentials ? . ExpiresAt > DateTime . Now . AddMilliseconds ( REFRESH_CREDENTIALS_SAFETY_PERIOD_MS ) )
50
+ if ( credentials != null )
47
51
{
48
52
return credentials ;
49
53
}
54
+ return await PrefetchCredentials ( ) ;
55
+ }
50
56
51
- credentials = await connector . FetchCredentials ( ) ;
52
-
57
+ /// <summary>
58
+ /// Fetch a new set of credentials and cache it.
59
+ /// Until this call succeeds, GetCredentials will still return the old credentials.
60
+ /// This may be called before the current credentials have expired.
61
+ /// </summary>
62
+ public async Task < PowerSyncCredentials ? > PrefetchCredentials ( )
63
+ {
64
+ credentials = await FetchCredentials ( ) ;
53
65
return credentials ;
54
66
}
55
67
68
+ /// <summary>
69
+ /// Get credentials for PowerSync.
70
+ /// This should always fetch a fresh set of credentials - don't use cached values.
71
+ /// </summary>
72
+ public async Task < PowerSyncCredentials ? > FetchCredentials ( )
73
+ {
74
+ return await connector . FetchCredentials ( ) ;
75
+ }
76
+
77
+ /// <summary>
78
+ /// Immediately invalidate credentials.
79
+ /// This may be called when the current credentials have expired.
80
+ /// </summary>
81
+ public void InvalidateCredentials ( )
82
+ {
83
+ credentials = null ;
84
+ }
85
+
56
86
static string GetUserAgent ( )
57
87
{
58
88
object [ ] attributes = Assembly . GetExecutingAssembly ( )
@@ -76,6 +106,11 @@ public async Task<T> Get<T>(string path, Dictionary<string, string>? headers = n
76
106
using var client = new HttpClient ( ) ;
77
107
var response = await client . SendAsync ( request ) ;
78
108
109
+ if ( response . StatusCode == System . Net . HttpStatusCode . Unauthorized )
110
+ {
111
+ InvalidateCredentials ( ) ;
112
+ }
113
+
79
114
if ( ! response . IsSuccessStatusCode )
80
115
{
81
116
var errorMessage = await response . Content . ReadAsStringAsync ( ) ;
@@ -95,7 +130,12 @@ public async Task<T> Get<T>(string path, Dictionary<string, string>? headers = n
95
130
{
96
131
throw new HttpRequestException ( $ "HTTP { response . StatusCode } : No content") ;
97
132
}
98
- else
133
+
134
+ if ( response . StatusCode == System . Net . HttpStatusCode . Unauthorized )
135
+ {
136
+ InvalidateCredentials ( ) ;
137
+ }
138
+
99
139
if ( ! response . IsSuccessStatusCode )
100
140
{
101
141
var errorText = await response . Content . ReadAsStringAsync ( ) ;
0 commit comments