diff --git a/Backend/Controllers/LiftController.cs b/Backend/Controllers/LiftController.cs index d1c8307cc0..756907abbb 100644 --- a/Backend/Controllers/LiftController.cs +++ b/Backend/Controllers/LiftController.cs @@ -204,25 +204,45 @@ internal async Task ExportLiftFile(string projectId, string userI return new UnsupportedMediaTypeResult(); } - // Ensure project exists and has words + // Ensure project exists var proj = _projectService.GetProject(projectId); if (proj is null) { return new NotFoundObjectResult(projectId); } - var words = await _wordRepo.GetAllWords(projectId); - if (words.Count == 0) + + // Check if another export started + if (_liftService.IsExportInProgress(userId)) { - return new BadRequestResult(); + return new ConflictResult(); } - // Export the data to a zip, read into memory, and delete zip - var exportedFilepath = CreateLiftExport(projectId); + // Store in-progress status for the export + _liftService.SetExportInProgress(userId, true); - // Store the temporary path to the exported file for user to download later. - _liftService.StoreExport(userId, exportedFilepath); - await _notifyService.Clients.All.SendAsync("DownloadReady", userId); - return new OkObjectResult(projectId); + try + { + // Ensure project has words + var words = await _wordRepo.GetAllWords(projectId); + if (words.Count == 0) + { + _liftService.SetExportInProgress(userId, false); + return new BadRequestResult(); + } + + // Export the data to a zip, read into memory, and delete zip + var exportedFilepath = CreateLiftExport(projectId); + + // Store the temporary path to the exported file for user to download later. + _liftService.StoreExport(userId, exportedFilepath); + await _notifyService.Clients.All.SendAsync("DownloadReady", userId); + return new OkObjectResult(projectId); + } + catch (Exception error) + { + _liftService.SetExportInProgress(userId, false); + throw error; + } } internal string CreateLiftExport(string projectId) diff --git a/Backend/Interfaces/ILiftService.cs b/Backend/Interfaces/ILiftService.cs index 9fbf643699..b3f7c95dea 100644 --- a/Backend/Interfaces/ILiftService.cs +++ b/Backend/Interfaces/ILiftService.cs @@ -14,5 +14,7 @@ ILexiconMerger GetLiftImporterExp void StoreExport(string key, string filePath); string? RetrieveExport(string key); bool DeleteExport(string key); + void SetExportInProgress(string key, bool isInProgress); + bool IsExportInProgress(string key); } } diff --git a/Backend/Services/LiftApiServices.cs b/Backend/Services/LiftApiServices.cs index a672025fc2..45b172d545 100644 --- a/Backend/Services/LiftApiServices.cs +++ b/Backend/Services/LiftApiServices.cs @@ -89,6 +89,27 @@ public LiftService() _liftExports = new Dictionary(); } + private readonly string inProgress = "IN_PROGRESS"; + + /// Store status that a user's export is in-progress. + public void SetExportInProgress(string userId, bool isInProgress = true) + { + _liftExports.Remove(userId); + if (isInProgress) + { + _liftExports.Add(userId, inProgress); + } + } + + /// Query whether user has an in-progress export. + public bool IsExportInProgress(string userId) + { + if (!_liftExports.ContainsKey(userId)) + { + return false; + } + return _liftExports[userId] == inProgress; + } /// Store filePath for a user's Lift export. public void StoreExport(string userId, string filePath) @@ -101,7 +122,7 @@ public void StoreExport(string userId, string filePath) /// Path to the Lift file on disk. public string? RetrieveExport(string userId) { - if (!_liftExports.ContainsKey(userId)) + if (!_liftExports.ContainsKey(userId) || _liftExports[userId] == inProgress) { return null; }