Need to see if your shared folder is taking up space on your dropbox 👨💻? Find out how to check here.
Forum Discussion
Engg
2 years agoExplorer | Level 3
System.Threading.Tasks.TaskCanceledException: A task was canceled.
We have 500 machine which upload file at same time. We are getting RateLimitException. We are doing a retry after waiting rateLimitException.ErrorResponse.RetryAfter seconds.
to test this. I came up with a console app.
Following is my code
public async Task UploadDBparallelly(List<string> dbLocalFilesPath)
{
List<Task> tasks = new List<Task>();
foreach (var item in dbLocalFilesPath.Select((value, i) => new { i, value }))
{
string dbLocalPath = item.value;
int index = item.i;
Logger.Instance.LogInfo($"dbLocalPath: {dbLocalPath}");
tasks.Add(Task.Run(async () =>
{
try
{
//var uploadPathWithFileName = GetFilePathWithFileName(dbLocalPath);
// Your console app logic goes here
await Upload(dbLocalPath, GetFilePathWithFileName(dbLocalPath));
}
catch (Exception ex)
{
Logger.Instance.LogError($"Error Exception {ex}");
}
}));
}
try
{
await Task.WhenAll(tasks);
}
catch (Exception ex)
{
// Handle any exceptions thrown by tasks here
Logger.Instance.LogError($"Error Exception {ex}");
}
}
public static async Task Upload(string localPath, string remotePath)
{
try
{
string accessToken = ConfigurationManager.AppSettings["AccessToken"];
using (DropboxClient client = new DropboxClient(accessToken))
{
using (FileStream fileStream = System.IO.File.Open(localPath, FileMode.Open))
{
//Converting bytes to Megabyte
long fileSize = fileStream.Length / 1024 / 1024;
Logger.Instance.LogInfo($"Total File Size of backup file : {fileSize} MB");
//File Should be under 150MB
if (fileSize <= 150)
{
Logger.Instance.LogDebug("started direct upload backup to dropbox");
FilesUserRoutes files = client.Files;
string path = remotePath;
Stream stream = (Stream)fileStream;
DateTime? clientModified = new DateTime?();
Stream body = stream;
FileMetadata fileMetadata = await files.UploadAsync(path, clientModified: clientModified, body: body);
}
else
{
Logger.Instance.LogDebug("started chunk upload backup to dropbox");
const int chunkSize = 4096 * 1024;
await ChunkUpload(remotePath, fileStream, chunkSize, client, localPath);
}
}
}
}
catch (DropboxException dropboxException)
{
if (dropboxException.GetType().Name == typeof(RateLimitException).Name)
{
var rateLimitException = dropboxException as RateLimitException;
Logger.Instance.LogError($"Upload: Rate limit exceeded. Waiting before retrying...");
Logger.Instance.LogError($"Reason: {rateLimitException.ErrorResponse.Reason}: RetryAfter {rateLimitException.ErrorResponse.RetryAfter}");
var backoff = TimeSpan.FromSeconds(rateLimitException.ErrorResponse.RetryAfter);
Thread.Sleep(Convert.ToInt32(rateLimitException.ErrorResponse.RetryAfter) * 1000);
await Upload(localPath, remotePath); // Retry after delay
}
else
{
Logger.Instance.LogError($"dropboxException {dropboxException}");
}
}
catch (Exception ex)
{
Logger.Instance.LogError("Error in upload backup to dropbox", ex);
throw ex;
}
}
private static async Task ChunkUpload(string remotePath, FileStream fileStream, int chunkSize, DropboxClient client, string localPath)
{
try
{
Console.WriteLine($"Chunk upload file...{localPath}");
int numChunks = (int)Math.Ceiling((double)fileStream.Length / chunkSize);
Console.WriteLine($"SnumChunks {numChunks} ");
byte[] buffer = new byte[chunkSize];
string sessionId = null;
for (var idx = 0; idx < numChunks; idx++)
{
Console.WriteLine($"Start uploading chunk {idx} , LocalPath {localPath} ");
var byteRead = fileStream.Read(buffer, 0, chunkSize);
using (MemoryStream memStream = new MemoryStream(buffer, 0, byteRead))
{
if (idx == 0)
{
var result = client.Files.UploadSessionStartAsync(body: memStream).GetAwaiter().GetResult();
sessionId = result.SessionId;
}
else
{
UploadSessionCursor cursor = new UploadSessionCursor(sessionId, (ulong)(chunkSize * idx));
if (idx == numChunks - 1)
{
Logger.Instance.LogInfo($"DONE FOR{localPath}");
await client.Files.UploadSessionFinishAsync(cursor: cursor, commit: new CommitInfo(remotePath), body: memStream);
}
else
{
client.Files.UploadSessionAppendV2Async(cursor, body: memStream).GetAwaiter().GetResult();
}
}
}
}
}
catch (DropboxException dropboxException)
{
fileStream.Dispose();
client.Dispose();
if (dropboxException.GetType().Name == typeof(RateLimitException).Name)
{
var rateLimitException = dropboxException as RateLimitException;
Logger.Instance.LogError($"ChunkUpload: Rate limit exceeded. Waiting before retrying... RETRY FOR{localPath}");
Logger.Instance.LogError($"Reason: {rateLimitException.ErrorResponse.Reason}: RetryAfter {rateLimitException.ErrorResponse.RetryAfter}");
var backoff = TimeSpan.FromSeconds(rateLimitException.ErrorResponse.RetryAfter);
await Task.Delay(Convert.ToInt32(rateLimitException.ErrorResponse.RetryAfter) * 1000);
await Upload(localPath, remotePath); // Retry after delay
}
else
{
Logger.Instance.LogError($"dropboxException {dropboxException}");
}
}
catch (Exception ex)
{
Logger.Instance.LogError($"Error in chunk upload process {remotePath}", ex);
}
finally
{
fileStream.Dispose();
client.Dispose();
}
}
I'm getting following exception. What I might be missing?
System.Threading.Tasks.TaskCanceledException: A task was canceled.
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Dropbox.Api.DropboxRequestHandler.<RequestJsonString>d__2f.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Dropbox.Api.DropboxRequestHandler.<RequestJsonStringWithRetry>d__1a.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Dropbox.Api.DropboxRequestHandler.<Dropbox.Api.Stone.ITransport.SendUploadRequestAsync>d__d`3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Odin.Compute.OdinDatabaseBackupManager.DropboxUploadTest.<ChunkUpload>d__9.MoveNext() in C:\Work\AWC\AWC TFS\GIT\The ONE Platform\Source\Odin.Compute.OdinDatabaseBackupManager\DropboxUploadTest.cs:line 179
In general modifying the folder should not affect probability for exception appearing, but cannot prevent it. Some decrement may happen if different files/folders appear in different namespaces (namespaces are locked independently, so less likely compete), but better don't rely on.
Again, try to schedule the uploads in non overlap way and handle the possible exception in proper way. Example of such exception handling (again just example and far from optimal) follows:
private readonly int retryLimit = 20; ... var backoff = 0; var rand = new Random(); var commitInfo = new CommitInfo(filePath.Substring(filePath.LastIndexOf('/')), WriteMode.Overwrite.Instance, false); for (var i = 0; i < retryLimit && !string.IsNullOrEmpty(sessionId); ++i) { if (backoff != 0) { Console.WriteLine("Ограничение при завършване на файл {0}. Нов опит след {1} милисекунди...", commitInfo.Path, backoff); Thread.Sleep(backoff); } lastCursor = new UploadSessionCursor(sessionId, (ulong)fileStream.Length); memStream = new MemoryStream(buffer, 0, 0); try { await dbx.Files.UploadSessionFinishAsync(lastCursor, commitInfo, body: memStream); sessionId = string.Empty; } catch (RateLimitException rateLimit) { backoff = (int)(backoff * 1.1); backoff = Math.Max(backoff, rateLimit.RetryAfter * 1000); backoff = Math.Max(backoff, 1000); backoff += rand.Next(500); } } if (string.IsNullOrEmpty(sessionId)) { Console.WriteLine("Качването на {0} приключи \ud83d\ude09.", commitInfo.Path); } else { Console.WriteLine("Неуспешно завършване на файл {0} след {1} опита \ud83d\ude15!", commitInfo.Path, retryLimit); }The above just shows how my advices (from previous page) can be implemented. Here sessionId represents a session ready for finishing (i.e. content uploaded already).
11 Replies
Replies have been turned off for this discussion
- Здравко2 years agoLegendary | Level 20
In general modifying the folder should not affect probability for exception appearing, but cannot prevent it. Some decrement may happen if different files/folders appear in different namespaces (namespaces are locked independently, so less likely compete), but better don't rely on.
Again, try to schedule the uploads in non overlap way and handle the possible exception in proper way. Example of such exception handling (again just example and far from optimal) follows:
private readonly int retryLimit = 20; ... var backoff = 0; var rand = new Random(); var commitInfo = new CommitInfo(filePath.Substring(filePath.LastIndexOf('/')), WriteMode.Overwrite.Instance, false); for (var i = 0; i < retryLimit && !string.IsNullOrEmpty(sessionId); ++i) { if (backoff != 0) { Console.WriteLine("Ограничение при завършване на файл {0}. Нов опит след {1} милисекунди...", commitInfo.Path, backoff); Thread.Sleep(backoff); } lastCursor = new UploadSessionCursor(sessionId, (ulong)fileStream.Length); memStream = new MemoryStream(buffer, 0, 0); try { await dbx.Files.UploadSessionFinishAsync(lastCursor, commitInfo, body: memStream); sessionId = string.Empty; } catch (RateLimitException rateLimit) { backoff = (int)(backoff * 1.1); backoff = Math.Max(backoff, rateLimit.RetryAfter * 1000); backoff = Math.Max(backoff, 1000); backoff += rand.Next(500); } } if (string.IsNullOrEmpty(sessionId)) { Console.WriteLine("Качването на {0} приключи \ud83d\ude09.", commitInfo.Path); } else { Console.WriteLine("Неуспешно завършване на файл {0} след {1} опита \ud83d\ude15!", commitInfo.Path, retryLimit); }The above just shows how my advices (from previous page) can be implemented. Here sessionId represents a session ready for finishing (i.e. content uploaded already).
About Dropbox API Support & Feedback
Find help with the Dropbox API from other developers.
The Dropbox Community team is active from Monday to Friday. We try to respond to you as soon as we can, usually within 2 hours.
If you need more help you can view your support options (expected response time for an email or ticket is 24 hours), or contact us on X, Facebook or Instagram.
For more info on available support options for your Dropbox plan, see this article.
If you found the answer to your question in this Community thread, please 'like' the post to say thanks and to let us know it was useful!