diff --git a/src/PollinationSDK/ManuallyAdded/Model/JobPathArgument.cs b/src/PollinationSDK/ManuallyAdded/Model/JobPathArgument.cs new file mode 100644 index 00000000..113c0901 --- /dev/null +++ b/src/PollinationSDK/ManuallyAdded/Model/JobPathArgument.cs @@ -0,0 +1,38 @@ + +namespace PollinationSDK +{ + public partial class JobPathArgument + { + public void IsAssetUploaded(bool uploaded) + { + if (this.Annotations == null) + this.Annotations = new System.Collections.Generic.Dictionary(); + + var p = "Uploaded"; + var v = uploaded ? "true" : "false"; + + if (this.Annotations.TryGetValue(p, out var path)) + { + this.Annotations[p] = v; + } + else + { + this.Annotations.Add(p, v); + } + } + + public bool IsAssetUploaded() + { + if (this.Annotations == null) + return false; + + if (this.Annotations.TryGetValue("Uploaded", out var isUploaded)) + { + return isUploaded == "true"; + } + + return false; + + } + } +} \ No newline at end of file diff --git a/src/PollinationSDK/Wrapper/JobInfo.cs b/src/PollinationSDK/Wrapper/JobInfo.cs index 94129181..363e79c1 100644 --- a/src/PollinationSDK/Wrapper/JobInfo.cs +++ b/src/PollinationSDK/Wrapper/JobInfo.cs @@ -286,6 +286,19 @@ private async Task RunJobOnCloudAsync(Action progressR return jobInfo; } + public async Task UploadJobAssetsAsync(Action progressReporting = default, System.Threading.CancellationToken token = default) + { + if (string.IsNullOrEmpty(this.ProjectSlug) || this.IsLocalJob) + throw new ArgumentException($"Please call SetCloudJob() before running a job"); + + var proj = GetWritableProject(); + var runner = new JobRunner(this); + var newJob = await JobRunner.UploadJobAssetsAsync(proj, this.Job, this.SubFolderPath, progressReporting, token); + + return newJob; + } + + public void AddArgument(JobArgument arg) => this.Job.AddArgument(arg); public void AddArgument(JobPathArgument arg) => this.Job.AddArgument(arg); diff --git a/src/PollinationSDK/Wrapper/JobRunner.cs b/src/PollinationSDK/Wrapper/JobRunner.cs index 14aadb74..5ed7d348 100644 --- a/src/PollinationSDK/Wrapper/JobRunner.cs +++ b/src/PollinationSDK/Wrapper/JobRunner.cs @@ -50,6 +50,44 @@ public async Task RunOnCloudAsync(Project project, Action prog } + public static async Task UploadJobAssetsAsync( + Project project, + Job job, + string subfolderPath, + Action progressLogAction = default, + CancellationToken cancellationToken = default, + Action actionWhenDone = default) + { + // check artifacts + var tempProjectDir = CheckArtifacts(job, subfolderPath); + + // upload artifacts + if (!string.IsNullOrEmpty(tempProjectDir)) + { + Action updateMessageProgress = (int p) => { + progressLogAction?.Invoke($"Preparing: [{p}%]"); + }; + await Helper.UploadDirectoryAsync(project, tempProjectDir, updateMessageProgress, cancellationToken); + } + + // suspended by user + var emptyID = Guid.Empty; + if (cancellationToken.IsCancellationRequested) + { + progressLogAction?.Invoke($"Canceled: {cancellationToken.IsCancellationRequested}"); + Helper.Logger.Information($"ScheduleRunAsync: canceled by user"); + return null; + } + + // update Artifact to cloud's relative path after uploaded. + var newJob = UpdateArtifactPath(job, subfolderPath); + + actionWhenDone?.Invoke(); + + return newJob; + } + + /// /// Run and monitor the simulation on Pollination /// @@ -68,38 +106,13 @@ private async Task ScheduleCloudJobAsync( { // Get project var proj = project; - //var job = this._Job; // Check if recipe can be used in this project CheckRecipeInProject(job.Source, proj); // Upload artifacts - - // check artifacts - var tempProjectDir = CheckArtifacts(job, this.JobInfo.SubFolderPath); - - // upload artifacts - if (!string.IsNullOrEmpty(tempProjectDir)) - { - Action updateMessageProgress = (int p) => { - progressLogAction?.Invoke($"Preparing: [{p}%]"); - }; - await Helper.UploadDirectoryAsync(proj, tempProjectDir, updateMessageProgress, cancellationToken); - } - - // suspended by user - var emptyID = Guid.Empty; - if (cancellationToken.IsCancellationRequested) - { - progressLogAction?.Invoke($"Canceled: {cancellationToken.IsCancellationRequested}"); - Helper.Logger.Information($"ScheduleRunAsync: canceled by user"); - return null; - } - - // update Artifact to cloud's relative path after uploaded. - var newJob = UpdateArtifactPath(job, this.JobInfo.SubFolderPath); - //var json = newJob.ToJson(); - + var newJob = await UploadJobAssetsAsync(project, job, this.JobInfo.SubFolderPath, progressLogAction, cancellationToken); + // create a new Simulation var api = new JobsApi(); progressLogAction?.Invoke($"Start running."); @@ -306,7 +319,7 @@ private static string CheckArtifacts(Job job, string subFolderPath) var temp = string.Empty; var arg = job.Arguments; - var artis = arg.SelectMany(_=>_.OfType()); + var artis = arg.SelectMany(_ => _.OfType()).Where(_ => !_.IsAssetUploaded()); if (artis == null || !artis.Any()) return temp; // remove old temp files first @@ -391,6 +404,13 @@ private static Job UpdateArtifactPath(Job job, string subFolderPath) { if (item.Obj is JobPathArgument path) { + if (path.IsAssetUploaded()) + { + // do nothing + newJob.AddArgument(path); + continue; + } + // only update the path for ProjectFolderSource for a relative path var projFolderSource = path.Source.Obj as ProjectFolder; if (projFolderSource == null) continue; @@ -400,6 +420,7 @@ private static Job UpdateArtifactPath(Job job, string subFolderPath) if (!string.IsNullOrEmpty(subFolderPath)) newFileOrDirname = $"{subFolderPath}/{newFileOrDirname}"; var pSource = new ProjectFolder(path: newFileOrDirname); var newPath = new JobPathArgument(path.Name, pSource); + newPath.IsAssetUploaded(true); // add it to the last available argument set. newJob.AddArgument(newPath); @@ -418,6 +439,8 @@ private static Job UpdateArtifactPath(Job job, string subFolderPath) return newJob; } + + }