Skip to content

Commit

Permalink
Create zip file first, then return it
Browse files Browse the repository at this point in the history
This is less efficient, but the only method that actually works given
the current state of the ZipFile / ZipArchive code in .NET.
  • Loading branch information
rmunn committed Jan 15, 2025
1 parent a39a21b commit f8b0dba
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 5 deletions.
11 changes: 11 additions & 0 deletions backend/LexBoxApi/Controllers/ProjectController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,17 @@ private async Task StreamHttpResponse(HttpContent hgResult)
await hgResult.CopyToAsync(writer.AsStream());
}

[HttpGet("getLdmlZip")] // TODO: Discuss endpoint name, and whether it should be GET or POST, at next opportunity
[AdminRequired] // TODO: Decide on permissions, because we don't want everyone triggering this
public async Task GetLdmlZip(CancellationToken token)
{
var path = await projectService.PrepareLdmlZip(token);
Response.Headers.ContentDisposition = "attachment;filename=\"ldml.zip\""; // TODO: Put timestamp in filename, or use the filename that PrepareLdmlZip returns once it has a timestamp in it
Response.ContentType = "application/zip";
Response.StatusCode = 200;
await Response.SendFileAsync(path, token);
}

[HttpPost("updateMissingLanguageList")]
public async Task<ActionResult<string[]>> UpdateMissingLanguageList(int limit = 10)
{
Expand Down
3 changes: 2 additions & 1 deletion backend/LexBoxApi/Jobs/DelayedLexJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ protected static async Task QueueJob(ISchedulerFactory schedulerFactory,
data[nameof(JobTriggerTraceId)] = Activity.Current?.Context.TraceId.ToHexString() ?? string.Empty;
data[nameof(JobTriggerSpanParentId)] = Activity.Current?.Context.SpanId.ToHexString() ?? string.Empty;
var trigger = TriggerBuilder.Create()
.WithIdentity(key.Name + "_Trigger", key.Group)
// TODO: Is there a simpler way of telling Quartz "Hey, enqueue this job after X delay"? Picking a unique trigger name each time seems unnecessarily complicated.
.WithIdentity(key.Name + "_Trigger_" + now.Ticks.ToString(), key.Group)
.StartAt(now.Add(delay))
.ForJob(key.Name, key.Group)
.UsingJobData(data)
Expand Down
11 changes: 8 additions & 3 deletions backend/LexBoxApi/Services/ProjectService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,17 +283,22 @@ public async Task ResetLexEntryCount(string projectCode)
return dirInfo;
}

public async Task PrepareLdmlZip(Stream outStream, CancellationToken token = default)
public async Task<string> PrepareLdmlZip(CancellationToken token = default)
{
var path = System.IO.Path.Join(System.IO.Path.GetTempPath(), "ldml-zip"); // TODO: pick random name, rather than predictable one
if (Directory.Exists(path)) Directory.Delete(path, true);
Directory.CreateDirectory(path);
await DeleteTempDirectoryJob.Queue(schedulerFactory, path, TimeSpan.FromHours(4));
var zipRoot = System.IO.Path.Join(path, "zipRoot");
Directory.CreateDirectory(zipRoot);
await foreach (var project in dbContext.Projects.Where(p => p.Type == ProjectType.FLEx).AsAsyncEnumerable())
{
await ExtractLdmlZip(project, path, token);
await ExtractLdmlZip(project, zipRoot, token);
}
ZipFile.CreateFromDirectory(path, outStream, CompressionLevel.Fastest, includeBaseDirectory: false);
var zipFilePath = System.IO.Path.Join(path, "ldml.zip"); // TODO: Put timestamp in there
if (File.Exists(zipFilePath)) File.Delete(zipFilePath);
ZipFile.CreateFromDirectory(zipRoot, zipFilePath, CompressionLevel.Fastest, includeBaseDirectory: false);
return zipFilePath;
}

public async Task<DateTimeOffset?> UpdateLastCommit(string projectCode)
Expand Down
3 changes: 2 additions & 1 deletion hgweb/command-runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ fi

if [[ $command_name == "ldmlzip" ]]; then
# Preflight check: ldml zip access is only allowed if LexiconSettings.plsx contains addToSldr="true"
if (chg -R /var/hg/repos/$first_char/$project_code cat -r tip CachedSettings/SharedSettings/LexiconSettings.plsx | grep '<WritingSystems' | grep 'addToSldr="true"'); then
first_char=$(echo $project_code | cut -c1)
if (chg --cwd /var/hg/repos/$first_char/$project_code cat -r tip CachedSettings/SharedSettings/LexiconSettings.plsx | grep '<WritingSystems' | grep 'addToSldr="true"' >/dev/null); then
CONTENT_TYPE="application/zip"
else
echo "Content-type: text/plain"
Expand Down

0 comments on commit f8b0dba

Please sign in to comment.