Skip to content

Commit 02c0d2b

Browse files
authored
Merge pull request #185 from Nfactor26/published-prefab-version-download
Download published prefab version only if data is not locally available
2 parents cca7578 + 49c019d commit 02c0d2b

File tree

10 files changed

+130
-29
lines changed

10 files changed

+130
-29
lines changed

src/Pixel.Automation.Core/Models/VersionInfo.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ public abstract class VersionInfo
2828
[DataMember(IsRequired = false, Order = 30)]
2929
public string DataModelAssembly { get; set; }
3030

31+
/// <summary>
32+
/// DateTime when the version was publisheds
33+
/// </summary>
34+
[DataMember(IsRequired = false, Order = 40)]
35+
public DateTime? PublishedOn { get; set; }
36+
3137
/// <summary>
3238
/// Description
3339
/// </summary>
@@ -46,6 +52,12 @@ public override bool Equals(object obj)
4652
return false;
4753
}
4854

55+
///</inheritdoc>
56+
public override int GetHashCode()
57+
{
58+
return HashCode.Combine(this.Version, this.IsActive);
59+
}
60+
4961
///</inheritdoc>
5062
public override string ToString()
5163
{

src/Pixel.Automation.Designer.ViewModels/AppBootStrapper.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ protected override void OnStartup(object sender, StartupEventArgs e)
6363
logger.Information("Downloading project information now");
6464
await projectDataManager.DownloadProjectsAsync();
6565
logger.Information("Download of project information completed");
66-
await prefabDataManager.DownloadPrefabsAsync();
67-
logger.Information("Download of prefabs completed");
66+
await prefabDataManager.DownloadPrefabsAsync();
6867
}
6968
catch (Exception ex)
7069
{

src/Pixel.Automation.Designer.ViewModels/AutomationBuilder/AutomationProjectManager.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ public async Task<Entity> Load(AutomationProject activeProject, VersionInfo ver
5353

5454
foreach(var prefabReference in this.referenceManager.GetPrefabReferences().References)
5555
{
56-
await this.prefabDataManager.DownloadPrefabDataAsync(new PrefabProject() { ApplicationId = prefabReference.ApplicationId, PrefabId = prefabReference.PrefabId },
57-
prefabReference.Version);
56+
await this.prefabDataManager.DownloadPrefabDataAsync(prefabReference.ApplicationId, prefabReference.PrefabId, prefabReference.Version.ToString());
5857
}
5958

6059
this.entityManager.SetCurrentFileSystem(this.fileSystem);

src/Pixel.Automation.Test.Runner/ProjectManager.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,7 @@ public async Task LoadProjectAsync(string projectId, string projectVersion, stri
107107

108108
foreach (var prefabReference in this.referenceManager.GetPrefabReferences().References)
109109
{
110-
await this.prefabDataManager.DownloadPrefabDataAsync(new Core.Models.PrefabProject()
111-
{
112-
ApplicationId = prefabReference.ApplicationId,
113-
PrefabId = prefabReference.PrefabId
114-
},
115-
prefabReference.Version);
110+
await this.prefabDataManager.DownloadPrefabDataAsync( prefabReference.ApplicationId, prefabReference.PrefabId, prefabReference.Version.ToString());
116111
}
117112

118113
this.entityManager.SetCurrentFileSystem(this.projectFileSystem);

src/Pixel.Persistence.Core/Models/VersionInfo.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ public abstract class VersionInfo
2727
[DataMember(IsRequired = false, Order = 30)]
2828
public string DataModelAssembly { get; set; }
2929

30+
31+
[DataMember(IsRequired = false, Order = 40)]
32+
public DateTime? PublishedOn { get; set; }
33+
34+
3035
public override bool Equals(object obj)
3136
{
3237
if(obj is VersionInfo versionInfo)
@@ -38,7 +43,7 @@ public override bool Equals(object obj)
3843

3944
public override int GetHashCode()
4045
{
41-
return HashCode.Combine(Version, IsActive, DataModelAssembly);
46+
return HashCode.Combine(Version, IsActive);
4247
}
4348

4449
public override string ToString()

src/Pixel.Persistence.Respository/PrefabsRepository.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ public async Task AddPrefabVersionAsync(string prefabId, PrefabVersion newVersio
8080
var projectVersions = (await this.prefabsCollection.FindAsync<List<PrefabVersion>>(filter, new FindOptions<PrefabProject, List<PrefabVersion>>()
8181
{
8282
Projection = Builders<PrefabProject>.Projection.Expression(u => u.AvailableVersions)
83-
})).ToList().FirstOrDefault();
83+
}))
84+
.ToList().FirstOrDefault();
85+
8486
if (projectVersions?.Contains(newVersion) ?? false)
8587
{
8688
throw new InvalidOperationException($"Version {newVersion} already exists for prefab {prefabId}");
@@ -113,6 +115,10 @@ public async Task UpdatePrefabVersionAsync(string prefabId, PrefabVersion prefab
113115

114116
if (prefabVersions?.Contains(prefabVersion) ?? false)
115117
{
118+
if(!prefabVersion.IsActive && prefabVersion.PublishedOn is null)
119+
{
120+
prefabVersion.PublishedOn = DateTime.UtcNow;
121+
}
116122
var update = Builders<PrefabProject>.Update.Set(x => x.AvailableVersions[-1], prefabVersion);
117123
await this.prefabsCollection.UpdateOneAsync(filter, update);
118124
logger.LogInformation("Project version {0} was updated for project : {1}", prefabVersion, prefabId);

src/Pixel.Persistence.Respository/ProjectsRepository.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,15 @@ public async Task UpdateProjectVersionAsync(string projectId, ProjectVersion pro
146146
var projectVersions = (await this.projectsCollection.FindAsync<List<ProjectVersion>>(filter, new FindOptions<AutomationProject, List<ProjectVersion>>()
147147
{
148148
Projection = Builders<AutomationProject>.Projection.Expression(u => u.AvailableVersions)
149-
})).ToList().FirstOrDefault();
149+
}))
150+
.ToList().FirstOrDefault();
150151

151152
if (projectVersions?.Contains(projectVersion) ?? false)
152153
{
154+
if (!projectVersion.IsActive && projectVersion.PublishedOn is null)
155+
{
156+
projectVersion.PublishedOn = DateTime.UtcNow;
157+
}
153158
var update = Builders<AutomationProject>.Update.Set(x => x.AvailableVersions[-1], projectVersion);
154159
await this.projectsCollection.UpdateOneAsync(filter, update);
155160
logger.LogInformation("Project version {0} was updated for project : {1}", projectVersion, projectId);

src/Pixel.Persistence.Services.Client/DataManagers/PrefabDataManager.cs

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ public class PrefabDataManager : IPrefabDataManager
2626

2727
bool IsOnlineMode => !this.applicationSettings.IsOfflineMode;
2828

29+
/// <summary>
30+
/// constructor
31+
/// </summary>
32+
/// <param name="applicationSettings"></param>
33+
/// <param name="serializer"></param>
34+
/// <param name="applicationFileSystem"></param>
35+
/// <param name="prefabsRepositoryClient"></param>
36+
/// <param name="filesRepositoryClient"></param>
37+
/// <param name="referencesRepositoryClient"></param>
2938
public PrefabDataManager(ApplicationSettings applicationSettings, ISerializer serializer, IApplicationFileSystem applicationFileSystem,
3039
IPrefabsRepositoryClient prefabsRepositoryClient, IPrefabFilesRepositoryClient filesRepositoryClient, IReferencesRepositoryClient referencesRepositoryClient)
3140
{
@@ -37,6 +46,7 @@ public PrefabDataManager(ApplicationSettings applicationSettings, ISerializer se
3746
this.applicationFileSystem = Guard.Argument(applicationFileSystem).NotNull().Value;
3847
}
3948

49+
///<inheritdoc/>
4050
public IEnumerable<PrefabProject> GetAllPrefabs(string applicationId)
4151
{
4252
if (!prefabsCache.ContainsKey(applicationId))
@@ -46,6 +56,7 @@ public IEnumerable<PrefabProject> GetAllPrefabs(string applicationId)
4656
return prefabsCache[applicationId];
4757
}
4858

59+
///<inheritdoc/>
4960
public IEnumerable<PrefabProject> GetPrefabsForScreen(ApplicationDescription applicationDescription, string screenName)
5061
{
5162
if (applicationDescription.AvailablePrefabs.ContainsKey(screenName))
@@ -63,15 +74,38 @@ public IEnumerable<PrefabProject> GetPrefabsForScreen(ApplicationDescription app
6374
yield break;
6475
}
6576

77+
///<inheritdoc/>
78+
public async Task DownloadPrefabDataAsync(string applicationId, string prefabId, string prefabVersion)
79+
{
80+
Guard.Argument(applicationId, nameof(applicationId)).NotNull().NotEmpty();
81+
Guard.Argument(prefabId, nameof(prefabId)).NotNull().NotEmpty();
82+
Guard.Argument(prefabVersion, nameof(prefabVersion)).NotNull().NotEmpty();
83+
var prefabProject = LoadPrefabFromLocalStorage(applicationId, prefabId);
84+
var versionToDownload = prefabProject.AvailableVersions.FirstOrDefault(a => a.Version.ToString().Equals(prefabVersion))
85+
?? throw new ArgumentException($"Version {prefabVersion} doesn't exist for prefab {prefabProject.PrefabName}");
86+
await DownloadPrefabDataAsync(prefabProject, versionToDownload);
87+
}
88+
89+
///<inheritdoc/>
6690
public async Task DownloadPrefabDataAsync(PrefabProject prefabProject, PrefabVersion prefabVersion)
6791
{
92+
Guard.Argument(prefabProject, nameof(prefabProject)).NotNull();
93+
Guard.Argument(prefabVersion, nameof(prefabVersion)).NotNull();
94+
6895
var prefabsDirectory = Path.Combine(this.applicationFileSystem.GetPrefabProjectDirectory(prefabProject), prefabVersion.ToString());
69-
if(!Directory.Exists(prefabsDirectory))
96+
if (!Directory.Exists(prefabsDirectory))
7097
{
7198
Directory.CreateDirectory(prefabsDirectory);
72-
}
99+
}
100+
73101
if(IsOnlineMode)
74-
{
102+
{
103+
if(HasMostRecentDataAlreadyAvailable())
104+
{
105+
logger.Information("Skip download of version {0} of prefab project {1}. Data already available.", prefabVersion, prefabProject.PrefabName);
106+
return;
107+
}
108+
75109
//Download project references data
76110
var projectReferences = await this.referencesRepositoryClient.GetProjectReferencesAsync(prefabProject.PrefabId, prefabVersion.ToString());
77111
if (projectReferences != null)
@@ -80,9 +114,27 @@ public async Task DownloadPrefabDataAsync(PrefabProject prefabProject, PrefabVer
80114
this.serializer.Serialize(prefabReferencesFile, projectReferences);
81115
}
82116
await DownloadFilesWithTagsAsync(prefabProject, prefabVersion, new[] { prefabProject.PrefabId });
117+
logger.Information("Download completed for version {0} of prefab project {1}", prefabVersion, prefabProject.PrefabName);
118+
}
119+
120+
bool HasMostRecentDataAlreadyAvailable()
121+
{
122+
string lastUpdatedDataFile = Path.Combine(prefabsDirectory, Constants.LastUpdatedFileName);
123+
DateTime lastUpdated = DateTime.MinValue.ToUniversalTime();
124+
if (File.Exists(lastUpdatedDataFile))
125+
{
126+
if (!DateTime.TryParse(File.ReadAllText(lastUpdatedDataFile), out lastUpdated))
127+
{
128+
throw new Exception($"Failed to read last updated data from file : {lastUpdatedDataFile}");
129+
}
130+
File.Delete(lastUpdatedDataFile);
131+
}
132+
File.WriteAllText(lastUpdatedDataFile, DateTime.Now.ToUniversalTime().ToString("O"));
133+
return (prefabVersion.IsPublished && prefabVersion.PublishedOn < lastUpdated);
83134
}
84135
}
85136

137+
///<inheritdoc/>
86138
public async Task DownloadPrefabsAsync()
87139
{
88140
if (IsOnlineMode)
@@ -102,10 +154,11 @@ public async Task DownloadPrefabsAsync()
102154
}
103155
serializer.Serialize(prefabFile, prefab);
104156
}
157+
logger.Information("Download of Prefabs completed");
105158
}
106159
}
107160

108-
161+
///<inheritdoc/>
109162
public async Task AddPrefabAsync(PrefabProject prefabProject)
110163
{
111164
if (IsOnlineMode)
@@ -127,6 +180,8 @@ public async Task AddPrefabAsync(PrefabProject prefabProject)
127180
{
128181
await AddOrUpdateDataFileAsync(prefabProject, prefabProject.LatestActiveVersion, file, prefabProject.PrefabId);
129182
}
183+
184+
logger.Information("Prefab project {@prefabProject} was added.", prefabProject);
130185
}
131186

132187
////when a new prefab is created , add it to the prefabs cache
@@ -159,6 +214,7 @@ await this.filesClient.AddProjectDataFile(new Core.Models.ProjectDataFile()
159214
FilePath = Path.GetRelativePath(prefabsDirectory, filePath),
160215
Tag = tag,
161216
}, filePath);
217+
logger.Information("File {0} belonging to version {1} of prefab project {2} was added/updated.", Path.GetFileName(filePath), prefabVersion.ToString(), prefabProject.PrefabName);
162218
}
163219
}
164220

@@ -173,8 +229,10 @@ public async Task DeleteDataFileAsync(PrefabProject prefabProject, PrefabVersion
173229
{
174230
File.Delete(fileToDelete);
175231
}
232+
logger.Information("File {0} belonging to version {1} of prefab project {2} was deleted.", Path.GetFileName(fileToDelete), prefabVersion.ToString(), prefabProject.PrefabName);
176233
}
177234

235+
///<inheritdoc/>
178236
public async Task AddPrefabVersionAsync(PrefabProject prefabProject, PrefabVersion newVersion, PrefabVersion cloneFrom)
179237
{
180238
if (IsOnlineMode)
@@ -197,7 +255,6 @@ void CopyAll(DirectoryInfo source, DirectoryInfo target)
197255
{
198256
fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
199257
}
200-
201258
// Copy each subdirectory using recursion.
202259
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
203260
{
@@ -207,13 +264,13 @@ void CopyAll(DirectoryInfo source, DirectoryInfo target)
207264
}
208265
}
209266

210-
211267
prefabProject.AvailableVersions.Add(newVersion);
212268
string prefabDescriptionFile = this.applicationFileSystem.GetPrefabProjectFile(prefabProject);
213269
serializer.Serialize<PrefabProject>(prefabDescriptionFile, prefabProject);
214-
270+
logger.Information("Added new version {0} of prefab {1} from version {2}.", newVersion.ToString(), prefabProject.PrefabName, cloneFrom.ToString());
215271
}
216272

273+
///<inheritdoc/>
217274
public async Task UpdatePrefabVersionAsync(PrefabProject prefabProject, PrefabVersion prefabVersion)
218275
{
219276
if (IsOnlineMode)
@@ -222,37 +279,41 @@ public async Task UpdatePrefabVersionAsync(PrefabProject prefabProject, PrefabVe
222279
}
223280
string prefabDescriptionFile = this.applicationFileSystem.GetPrefabProjectFile(prefabProject);
224281
serializer.Serialize<PrefabProject>(prefabDescriptionFile, prefabProject);
282+
logger.Information("Version {0} of prefab {1} was updated.", prefabVersion.ToString(), prefabProject.PrefabName);
225283
}
226-
227-
public async Task SavePrefabDataAsync(PrefabProject prefabProject, PrefabVersion prefabVerssion)
284+
285+
///<inheritdoc/>
286+
public async Task SavePrefabDataAsync(PrefabProject prefabProject, PrefabVersion prefabVersion)
228287
{
229288
if (IsOnlineMode)
230289
{
231-
string projectDirectory = Path.Combine(this.applicationFileSystem.GetPrefabProjectDirectory(prefabProject), prefabVerssion.ToString());
290+
string projectDirectory = Path.Combine(this.applicationFileSystem.GetPrefabProjectDirectory(prefabProject), prefabVersion.ToString());
232291

233292
string processsFile = Path.Combine(projectDirectory, Constants.PrefabProcessFileName);
234-
await AddOrUpdateDataFileAsync(prefabProject, prefabVerssion, processsFile, prefabProject.PrefabId);
293+
await AddOrUpdateDataFileAsync(prefabProject, prefabVersion, processsFile, prefabProject.PrefabId);
235294

236295
string templateFile = Path.Combine(projectDirectory, Constants.PrefabTemplateFileName);
237296
if(File.Exists(templateFile))
238297
{
239-
await AddOrUpdateDataFileAsync(prefabProject, prefabVerssion, templateFile, prefabProject.PrefabId);
298+
await AddOrUpdateDataFileAsync(prefabProject, prefabVersion, templateFile, prefabProject.PrefabId);
240299
}
241300

242301
foreach (var file in Directory.EnumerateFiles(Path.Combine(projectDirectory, Constants.ReferencesDirectory), "*.*"))
243302
{
244-
await AddOrUpdateDataFileAsync(prefabProject, prefabVerssion, file, prefabProject.PrefabId);
303+
await AddOrUpdateDataFileAsync(prefabProject, prefabVersion, file, prefabProject.PrefabId);
245304
}
246305

247306
foreach (var file in Directory.EnumerateFiles(Path.Combine(projectDirectory, Constants.DataModelDirectory), "*.cs"))
248307
{
249-
await AddOrUpdateDataFileAsync(prefabProject, prefabVerssion, file, prefabProject.PrefabId);
308+
await AddOrUpdateDataFileAsync(prefabProject, prefabVersion, file, prefabProject.PrefabId);
250309
}
251310

252311
foreach (var file in Directory.EnumerateFiles(Path.Combine(projectDirectory, Constants.ScriptsDirectory), "*.csx"))
253312
{
254-
await AddOrUpdateDataFileAsync(prefabProject, prefabVerssion, file, prefabProject.PrefabId);
313+
await AddOrUpdateDataFileAsync(prefabProject, prefabVersion, file, prefabProject.PrefabId);
255314
}
315+
316+
logger.Information("Data for version {0} of prefab {1} was saved.", prefabVersion.ToString(), prefabProject.PrefabName);
256317
}
257318
}
258319

@@ -300,4 +361,15 @@ private List<PrefabProject> LoadPrefabsFromLocalStorage(string applicationId)
300361
return prefabProjects;
301362
}
302363

364+
private PrefabProject LoadPrefabFromLocalStorage(string applicationId, string prefabId)
365+
{
366+
var prefabProjectFile = Path.Combine(this.applicationFileSystem.GetApplicationPrefabsDirectory(applicationId), prefabId, $"{prefabId}.atm");
367+
if (File.Exists(prefabProjectFile))
368+
{
369+
PrefabProject prefabProject = serializer.Deserialize<PrefabProject>(prefabProjectFile);
370+
return prefabProject;
371+
}
372+
throw new FileNotFoundException($"File {prefabProjectFile} doesn't exist.");
373+
}
374+
303375
}

src/Pixel.Persistence.Services.Client/DataManagers/ProjectDataManager.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
using System.IO.Compression;
1212
using System.Linq;
1313
using System.Threading.Tasks;
14-
using static System.Net.Mime.MediaTypeNames;
1514

1615
namespace Pixel.Persistence.Services.Client;
1716

src/Pixel.Persistence.Services.Client/Interfaces/IPrefabDataManager.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ public interface IPrefabDataManager
2727
/// <returns></returns>
2828
Task DownloadPrefabsAsync();
2929

30+
/// <summary>
31+
/// Download data files for a given version of prefab
32+
/// </summary>
33+
/// <param name="applicationId"></param>
34+
/// <param name="prefabId"></param>
35+
/// <param name="prefabVersion"></param>
36+
/// <returns></returns>
37+
Task DownloadPrefabDataAsync(string applicationId, string prefabId, string prefabVersion);
38+
3039
/// <summary>
3140
/// Download data files for a given version of Prefab
3241
/// </summary>

0 commit comments

Comments
 (0)