Kaynağa Gözat

Extracted static ResourceCollection

Tim Jones 1 ay önce
ebeveyn
işleme
c5e5c42769

+ 2 - 0
README.md

@@ -10,6 +10,8 @@ If you run a home lab, you belong here.
 
 [![Join our Discord](https://img.shields.io/badge/Discord-Join%20Us-7289DA?logo=discord&logoColor=white)](https://discord.gg/egXRPdesee)
 
+[![Live Demo](https://img.shields.io/badge/Live%20Demo-Try%20RackPeek%20Online-2ea44f?logo=githubpages&logoColor=white)](https://timmoth.github.io/RackPeek/)
+
 
 ## Philosophy
 RackPeek treats infrastructure documentation as living reference data rather than static paperwork.

+ 23 - 24
RackPeek.Domain/Persistence/Yaml/YamlResourceCollection.cs

@@ -10,37 +10,36 @@ using YamlDotNet.Core;
 using YamlDotNet.Serialization;
 using YamlDotNet.Serialization.NamingConventions;
 
-public sealed class YamlResourceCollection : IResourceCollection
+public class ResourceCollection
 {
-    private readonly string _filePath;
-    private readonly ITextFileStore _fileStore;
-    private static readonly SemaphoreSlim _fileLock = new(1, 1);
-    private static readonly List<Resource> _resources = new();
-
-    public YamlResourceCollection(string filePath, ITextFileStore fileStore)
-    {
-        _filePath = filePath;
-        _fileStore = fileStore;
-    }
+    public List<Resource> Resources { get; } = new();
+    public readonly SemaphoreSlim FileLock = new(1, 1);
 
+}
+public sealed class YamlResourceCollection(
+    string filePath,
+    ITextFileStore fileStore,
+    ResourceCollection resourceCollection)
+    : IResourceCollection
+{
     public async Task LoadAsync()
     {
         var loaded = await LoadFromFileAsync();
-        _resources.Clear();
-        _resources.AddRange(loaded);
+        resourceCollection.Resources.Clear();
+        resourceCollection.Resources.AddRange(loaded);
     }
 
     public IReadOnlyList<Hardware> HardwareResources =>
-        _resources.OfType<Hardware>().ToList();
+        resourceCollection.Resources.OfType<Hardware>().ToList();
 
     public IReadOnlyList<SystemResource> SystemResources =>
-        _resources.OfType<SystemResource>().ToList();
+        resourceCollection.Resources.OfType<SystemResource>().ToList();
 
     public IReadOnlyList<Service> ServiceResources =>
-        _resources.OfType<Service>().ToList();
+        resourceCollection.Resources.OfType<Service>().ToList();
 
     public Resource? GetByName(string name) =>
-        _resources.FirstOrDefault(r =>
+        resourceCollection.Resources.FirstOrDefault(r =>
             r.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
 
     public Task AddAsync(Resource resource) =>
@@ -69,10 +68,10 @@ public sealed class YamlResourceCollection : IResourceCollection
 
     private async Task UpdateWithLockAsync(Action<List<Resource>> action)
     {
-        await _fileLock.WaitAsync();
+        await resourceCollection.FileLock.WaitAsync();
         try
         {
-            action(_resources);
+            action(resourceCollection.Resources);
 
             var serializer = new SerializerBuilder()
                 .WithNamingConvention(CamelCaseNamingConvention.Instance)
@@ -80,22 +79,22 @@ public sealed class YamlResourceCollection : IResourceCollection
 
             var payload = new OrderedDictionary
             {
-                ["resources"] = _resources.Select(SerializeResource).ToList()
+                ["resources"] = resourceCollection.Resources.Select(SerializeResource).ToList()
             };
 
-            await _fileStore.WriteAllTextAsync(
-                _filePath,
+            await fileStore.WriteAllTextAsync(
+                filePath,
                 serializer.Serialize(payload));
         }
         finally
         {
-            _fileLock.Release();
+            resourceCollection.FileLock.Release();
         }
     }
 
     private async Task<List<Resource>> LoadFromFileAsync()
     {
-        var yaml = await _fileStore.ReadAllTextAsync(_filePath);
+        var yaml = await fileStore.ReadAllTextAsync(filePath);
         if (string.IsNullOrWhiteSpace(yaml))
             return new();
 

+ 4 - 1
RackPeek.Web.Viewer/Program.cs

@@ -25,10 +25,13 @@ public class Program
         
         builder.Services.AddScoped<ITextFileStore, WasmTextFileStore>();
 
+        var resources = new ResourceCollection();
+        builder.Services.AddSingleton(resources);
         builder.Services.AddScoped<IResourceCollection>(sp =>
             new YamlResourceCollection(
                 "config.yaml",
-                sp.GetRequiredService<ITextFileStore>()));
+                sp.GetRequiredService<ITextFileStore>(),
+                sp.GetRequiredService<ResourceCollection>()));
         
         services.AddScoped<IHardwareRepository, YamlHardwareRepository>();
         services.AddScoped<ISystemRepository, YamlSystemRepository>();

+ 1 - 1
RackPeek.Web/Program.cs

@@ -36,7 +36,7 @@ public class Program
                 $"YAML directory not found: {yamlPath}"
             );
 
-        var collection = new YamlResourceCollection(Path.Combine(yamlDir, "config.yaml"), new PhysicalTextFileStore());
+        var collection = new YamlResourceCollection(Path.Combine(yamlDir, "config.yaml"), new PhysicalTextFileStore(), new ResourceCollection());
         await collection.LoadAsync();
 
         // Infrastructure

+ 1 - 1
RackPeek/CliBootstrap.cs

@@ -54,7 +54,7 @@ public static class CliBootstrap
 
         if (!Directory.Exists(yamlPath)) throw new DirectoryNotFoundException($"YAML directory not found: {yamlPath}");
 
-        var collection = new YamlResourceCollection(Path.Combine(yamlDir, yamlFile), new PhysicalTextFileStore());
+        var collection = new YamlResourceCollection(Path.Combine(yamlDir, yamlFile), new PhysicalTextFileStore(), new ResourceCollection());
         await collection.LoadAsync();
         services.AddSingleton<IResourceCollection>(collection);
 

+ 2 - 2
Tests/Yaml/HardwareDeserializationTests.cs

@@ -18,9 +18,9 @@ public class HardwareDeserializationTests
         Directory.CreateDirectory(tempDir);
 
         var filePath = Path.Combine(tempDir, "config.yaml");
-        File.WriteAllText(filePath, yaml);
+        await File.WriteAllTextAsync(filePath, yaml);
 
-        var yamlResourceCollection = new YamlResourceCollection(filePath, new PhysicalTextFileStore());
+        var yamlResourceCollection = new YamlResourceCollection(filePath, new PhysicalTextFileStore(), new ResourceCollection());
         await yamlResourceCollection.LoadAsync();
         return new YamlHardwareRepository(yamlResourceCollection);
     }

+ 2 - 2
Tests/Yaml/ServiceDeserializationTests.cs

@@ -17,9 +17,9 @@ public class ServiceDeserializationTests
         Directory.CreateDirectory(tempDir);
 
         var filePath = Path.Combine(tempDir, "config.yaml");
-        File.WriteAllText(filePath, yaml);
+        await File.WriteAllTextAsync(filePath, yaml);
 
-        var yamlResourceCollection = new YamlResourceCollection(filePath, new PhysicalTextFileStore());
+        var yamlResourceCollection = new YamlResourceCollection(filePath, new PhysicalTextFileStore(), new ResourceCollection());
         await yamlResourceCollection.LoadAsync();
 
         return new YamlServiceRepository(yamlResourceCollection);

+ 4 - 3
Tests/Yaml/SystemDeserializationTests.cs

@@ -16,12 +16,13 @@ public class SystemDeserializationTests
 
         Directory.CreateDirectory(tempDir);
 
-        var filePath = Path.Combine(tempDir, "config.yaml");
-        File.WriteAllText(filePath, yaml);
+        var filePath = Path.Combine(tempDir, "config.yaml"); 
+        await File.WriteAllTextAsync(filePath, yaml);
 
-        var yamlResourceCollection = new YamlResourceCollection(filePath, new PhysicalTextFileStore());
+        var yamlResourceCollection = new YamlResourceCollection(filePath, new PhysicalTextFileStore(), new ResourceCollection());
         await yamlResourceCollection.LoadAsync();
 
+        
         return new YamlSystemRepository(yamlResourceCollection);
     }