using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace AssetDependencyGraph { [BsonIgnoreExtraElements] public class AssetIdentify { public string Path; public string AssetType; [AllowNull] public string Guid; [AllowNull] public string Md5; } [BsonIgnoreExtraElements] public class AssetNode { public AssetIdentify Self; public string AssetType; public HashSet Dependencies = new(); public HashSet Dependent = new(); } [BsonIgnoreExtraElements] public sealed class FolderNode : AssetNode { } [BsonIgnoreExtraElements] public sealed class PackageNode : AssetNode { } public class AssetDependencyGraphDB { MongoClient client; IMongoCollection FolderNodes; IMongoCollection PackageNodes; IMongoCollection AssetNodes; Dictionary findCacheDic = new(); public AssetDependencyGraphDB(string user, string passwd, string ip) { MongoClientSettings settings; if(string.IsNullOrEmpty(user) && !string.IsNullOrEmpty(ip)) { settings = MongoClientSettings.FromUrl(new MongoUrl($"mongodb://{ip}:27017/")); } else { settings = MongoClientSettings.FromUrl(new MongoUrl($"mongodb://{user}:{passwd}@{ip}:27017/")); } settings.ConnectTimeout = TimeSpan.FromSeconds(5); settings.MinConnectionPoolSize = 1; settings.MaxConnectionPoolSize = 25; client = new MongoClient(settings); var db = client.GetDatabase("assetgraph"); FolderNodes = db.GetCollection("folder_nodes"); PackageNodes = db.GetCollection("package_nodes"); AssetNodes = db.GetCollection("asset_nodes"); } public void Clean() { client.DropDatabase("assetgraph"); var db = client.GetDatabase("assetgraph"); FolderNodes = db.GetCollection("folder_nodes"); PackageNodes = db.GetCollection("package_nodes"); AssetNodes = db.GetCollection("asset_nodes"); } public void UpdateOrInsert(T node) where T : AssetNode { switch (node) { case FolderNode folderNode: { var filter = Builders.Filter.And( Builders.Filter.Eq(fn=>fn.Self.Path,node.Self.Path) ); var found = FolderNodes.Find(filter); if (found == null || found.CountDocuments() == 0) { FolderNodes.InsertOne(folderNode); } else { var result = FolderNodes.UpdateOne(filter, Builders.Update.Combine( Builders.Update.Set(fn => fn.Self, folderNode.Self), Builders.Update.Set(fn => fn.AssetType, folderNode.AssetType), Builders.Update.Set(fn => fn.Dependencies, folderNode.Dependencies), Builders.Update.Set(fn => fn.Dependent, folderNode.Dependent) )); } break; } case PackageNode packageNode: { var filter = Builders.Filter.And( Builders.Filter.Eq(fn => fn.Self.Path, node.Self.Path) ); var found = PackageNodes.Find(filter); if (found == null || found.CountDocuments() == 0) { PackageNodes.InsertOne(packageNode); } else { var result = PackageNodes.UpdateOne(filter, Builders.Update.Combine( Builders.Update.Set(fn => fn.Self, packageNode.Self), Builders.Update.Set(fn => fn.AssetType, packageNode.AssetType), Builders.Update.Set(fn => fn.Dependencies, packageNode.Dependencies), Builders.Update.Set(fn => fn.Dependent, packageNode.Dependent) )); } break; } case AssetNode assetNode: { var filter = Builders.Filter.And( Builders.Filter.Eq(fn => fn.Self.Path, node.Self.Path) ); var found = AssetNodes.Find(filter); if (found == null || found.CountDocuments() == 0) { AssetNodes.InsertOne(assetNode); } else { var result = AssetNodes.UpdateOne(filter, Builders.Update.Combine( Builders.Update.Set(fn => fn.Self, assetNode.Self), Builders.Update.Set(fn => fn.AssetType, assetNode.AssetType), Builders.Update.Set(fn => fn.Dependencies, assetNode.Dependencies), Builders.Update.Set(fn => fn.Dependent, assetNode.Dependent) )); } break; } default: break; } } public void Delete(T node) where T : AssetNode { switch (node) { case FolderNode folderNode: { var filter = Builders.Filter.And( Builders.Filter.Eq(fn => fn.Self.Path, node.Self.Path) ); var found = FolderNodes.Find(filter); if (found != null && found.CountDocuments() == 0) { // TODO: del ref dep FolderNodes.DeleteOne(filter); } break; } case PackageNode packageNode: { var filter = Builders.Filter.And( Builders.Filter.Eq(fn => fn.Self.Path, node.Self.Path) ); var found = PackageNodes.Find(filter); if (found != null && found.CountDocuments() == 0) { // TODO: del ref dep PackageNodes.DeleteOne(filter); } break; } case AssetNode assetNode: { var filter = Builders.Filter.And( Builders.Filter.Eq(fn => fn.Self.Path, node.Self.Path) ); var found = AssetNodes.Find(filter); if (found != null && found.CountDocuments() == 0) { // TODO: del ref dep AssetNodes.DeleteOne(filter); } break; } default: break; } } public AssetNode Find(string path) { if(findCacheDic.TryGetValue(path, out var assetNode)) { return assetNode; } var filter = Builders.Filter.And( Builders.Filter.Eq(fn => fn.Self.Path, path) ); var found = AssetNodes.Find(filter); if (found != null && found.CountDocuments() != 0) { assetNode = found.First(); findCacheDic[path] = assetNode; return assetNode; } var filter1 = Builders.Filter.And( Builders.Filter.Eq(fn => fn.Self.Path, path) ); var found1 = PackageNodes.Find(filter1); if (found1 != null && found1.CountDocuments() != 0) { assetNode = found1.First(); findCacheDic[path] = assetNode; return assetNode; } var filter2 = Builders.Filter.And( Builders.Filter.Eq(fn => fn.Self.Path, path) ); var found2 = FolderNodes.Find(filter2); if (found2 != null && found2.CountDocuments() != 0) { assetNode = found2.First(); findCacheDic[path] = assetNode; return assetNode; } return null; } } }