Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cfeba48

Browse files
committedApr 17, 2024·
fix(UploadDirectoryAsync): batch upload to prevent timeout
1 parent aab69e8 commit cfeba48

File tree

4 files changed

+58
-24
lines changed

4 files changed

+58
-24
lines changed
 

‎src/PollinationSDK/Client/Configuration.cs

+1-5
Original file line numberDiff line numberDiff line change
@@ -301,11 +301,7 @@ public virtual string AccessToken
301301
{
302302
get
303303
{
304-
if (TokenRepo != null)
305-
{
306-
return TokenRepo.GetToken();
307-
}
308-
return "";
304+
return TokenRepo?.GetToken();
309305
}
310306
}
311307

‎src/PollinationSDK/Helper/AuthHelper.cs

+1
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ private static bool CheckGetUser(AuthResult auth, out string errorMessage, bool
199199
refreshURL: devEnv ? RefreshURL_Dev : RefreshURL,
200200
idToken: auth.IDToken,
201201
expiresInSeconds: auth.ExpiresInSeconds,
202+
//expiresInSeconds: 62, // for testing. expires in 1 minute, but it should be refreshed in 2 seconds.
202203
refreshToken: auth.RefreshToken
203204
);
204205
Helper.CurrentUser = Helper.GetUser();

‎src/PollinationSDK/Helper/Helper.cs

+41-12
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,49 @@ public static async Task<bool> UploadDirectoryAsync(Project project, string dire
9595

9696
var files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
9797
var api = new ArtifactsApi();
98-
9998

100-
var tasks = files.Select(_ => UploadArtifactAsync(api, project, _, _.Replace(directory, ""))).ToList();
10199
var total = files.Count();
102-
103100
LogHelper.LogInfo($"Uploading {total} assets for project {project.Name}");
104101

105-
102+
var finished = 0;
106103
var finishedPercent = 0;
107104
reportProgressAction?.Invoke(finishedPercent);
108105

106+
var chunkSize = 20;
107+
var subLists = files.Select((x, i) => new { Index = i, Value = x })
108+
.GroupBy(x => x.Index / chunkSize)
109+
.Select(x => x.Select(v => v.Value).ToList())
110+
.ToList();
111+
112+
Action<int> reportPercent = (c) =>
113+
{
114+
var p = finished + c;
115+
finishedPercent = (int)(p * 100 / total);
116+
reportProgressAction?.Invoke(finishedPercent);
117+
};
118+
119+
foreach (var chunk in subLists)
120+
{
121+
var chunkFiles = chunk.Select(_ => (_, _.Replace(directory, ""))).ToList();
122+
await BatchExecute(api, project, chunkFiles, reportPercent, cancellationToken);
123+
// auto refresh token between each chunk run
124+
api.Configuration.TokenRepo?.CheckToken();
125+
finished += chunk.Count;
126+
}
127+
128+
LogHelper.LogInfo($"Finished uploading assets for project {project.Name}");
129+
130+
// canceled by user
131+
if (cancellationToken.IsCancellationRequested) return false;
132+
133+
return true;
134+
}
135+
136+
private static async Task<bool> BatchExecute(ArtifactsApi api, Project project, List<(string path, string relativePath)> files , Action<int> finishedCountProgressAction = default, CancellationToken cancellationToken = default)
137+
{
138+
var tasks = files.Select(_=> UploadArtifactAsync(api, project, _.path, _.relativePath)).ToList();
139+
140+
var finished = 0;
109141
while (tasks.Count() > 0)
110142
{
111143
// canceled by user
@@ -116,25 +148,21 @@ public static async Task<bool> UploadDirectoryAsync(Project project, string dire
116148
}
117149

118150
var finishedTask = await Task.WhenAny(tasks);
151+
tasks.Remove(finishedTask);
119152

120153
if (finishedTask.IsFaulted || finishedTask.Exception != null)
121154
{
122155
LogHelper.LogError($"Upload exception: {finishedTask.Exception}");
123156
throw finishedTask.Exception;
124157
}
125158

126-
tasks.Remove(finishedTask);
127-
128-
var unfinishedUploadTasksCount = tasks.Count();
129-
finishedPercent = (int)((total - unfinishedUploadTasksCount) / (double)total * 100);
130-
reportProgressAction?.Invoke(finishedPercent);
159+
finished++;
160+
finishedCountProgressAction?.Invoke(finished);
131161

132162
}
133-
LogHelper.LogInfo($"Finished uploading assets for project {project.Name}");
134163

135164
// canceled by user
136165
if (cancellationToken.IsCancellationRequested) return false;
137-
138166
return true;
139167
}
140168

@@ -151,6 +179,7 @@ public static async Task<bool> UploadArtifactAsync(ArtifactsApi api, Project pro
151179
if (fileRelativePath.StartsWith("/"))
152180
fileRelativePath = fileRelativePath.Substring(1);
153181

182+
154183
var artf = await api.CreateArtifactAsync(project.Owner.Name, project.Name, new KeyRequest(fileRelativePath));
155184

156185
//Use RestSharp
@@ -171,7 +200,7 @@ public static async Task<bool> UploadArtifactAsync(ArtifactsApi api, Project pro
171200

172201
restRequest.AddFile("file", filePath);
173202

174-
LogHelper.LogInfo($"Started upload of {relativePath}");
203+
LogHelper.LogInfo($"Started upload of {fileRelativePath}");
175204
var response = await restClient.ExecuteAsync(restRequest);
176205

177206
if (response.StatusCode == HttpStatusCode.NoContent)

‎src/PollinationSDK/ManuallyAdded/Client/TokenRepo.cs

+15-7
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ public TokenRepo(string refreshURL, string idToken, int expiresInSeconds, string
1818
{
1919
RefreshURL = refreshURL;
2020
IDToken = idToken;
21-
ExpiresAt = DateTime.Now.AddSeconds(expiresInSeconds);
21+
22+
// make it expire 1 mins early so that it refresh token before expiration.
23+
ExpiresAt = DateTime.Now.AddSeconds(expiresInSeconds - 60);
2224
RefreshToken = refreshToken;
2325
this.LogTokenExpiration();
2426
}
@@ -52,7 +54,8 @@ private void DoTokenRefresh()
5254
}
5355

5456
this.IDToken = res.Data["id_token"];
55-
this.ExpiresAt = DateTime.Now.AddSeconds(int.Parse(res.Data["expires_in"]));
57+
var seconds = int.Parse(res.Data["expires_in"]);
58+
this.ExpiresAt = DateTime.Now.AddSeconds(seconds);
5659
this.RefreshToken = res.Data["refresh_token"];
5760
}
5861

@@ -63,13 +66,18 @@ private void DoTokenRefreshLogged()
6366
LogHelper.LogInfo("Token refresh finished");
6467
this.LogTokenExpiration();
6568
}
66-
public string GetToken()
69+
70+
public void CheckToken()
6771
{
68-
if (DateTime.Now >= this.ExpiresAt)
69-
{
70-
this.DoTokenRefreshLogged();
71-
}
72+
if (DateTime.Now < this.ExpiresAt)
73+
return;
7274

75+
this.DoTokenRefreshLogged();
76+
}
77+
78+
public string GetToken()
79+
{
80+
CheckToken();
7381
return this.IDToken;
7482
}
7583
}

0 commit comments

Comments
 (0)
Please sign in to comment.