2025-04-10 20:39:04 +08:00

234 lines
9.4 KiB
C#

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<AssetIdentify> Dependencies = new();
public HashSet<AssetIdentify> Dependent = new();
}
[BsonIgnoreExtraElements]
public sealed class FolderNode : AssetNode
{
}
[BsonIgnoreExtraElements]
public sealed class PackageNode : AssetNode
{
}
public class AssetDependencyGraphDB
{
MongoClient client;
IMongoCollection<FolderNode> FolderNodes;
IMongoCollection<PackageNode> PackageNodes;
IMongoCollection<AssetNode> AssetNodes;
Dictionary<string, AssetNode> findCacheDic = new();
public AssetDependencyGraphDB(string user, string passwd, string ip)
{
MongoClientSettings 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<FolderNode>("folder_nodes");
PackageNodes = db.GetCollection<PackageNode>("package_nodes");
AssetNodes = db.GetCollection<AssetNode>("asset_nodes");
}
public void Clean()
{
client.DropDatabase("assetgraph");
var db = client.GetDatabase("assetgraph");
FolderNodes = db.GetCollection<FolderNode>("folder_nodes");
PackageNodes = db.GetCollection<PackageNode>("package_nodes");
AssetNodes = db.GetCollection<AssetNode>("asset_nodes");
}
public void UpdateOrInsert<T>(T node) where T : AssetNode
{
switch (node)
{
case FolderNode folderNode:
{
var filter = Builders<FolderNode>.Filter.And(
Builders<FolderNode>.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<FolderNode>.Update.Combine(
Builders<FolderNode>.Update.Set(fn => fn.Self, folderNode.Self),
Builders<FolderNode>.Update.Set(fn => fn.AssetType, folderNode.AssetType),
Builders<FolderNode>.Update.Set(fn => fn.Dependencies, folderNode.Dependencies),
Builders<FolderNode>.Update.Set(fn => fn.Dependent, folderNode.Dependent)
));
}
break;
}
case PackageNode packageNode:
{
var filter = Builders<PackageNode>.Filter.And(
Builders<PackageNode>.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<PackageNode>.Update.Combine(
Builders<PackageNode>.Update.Set(fn => fn.Self, packageNode.Self),
Builders<PackageNode>.Update.Set(fn => fn.AssetType, packageNode.AssetType),
Builders<PackageNode>.Update.Set(fn => fn.Dependencies, packageNode.Dependencies),
Builders<PackageNode>.Update.Set(fn => fn.Dependent, packageNode.Dependent)
));
}
break;
}
case AssetNode assetNode:
{
var filter = Builders<AssetNode>.Filter.And(
Builders<AssetNode>.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<AssetNode>.Update.Combine(
Builders<AssetNode>.Update.Set(fn => fn.Self, assetNode.Self),
Builders<AssetNode>.Update.Set(fn => fn.AssetType, assetNode.AssetType),
Builders<AssetNode>.Update.Set(fn => fn.Dependencies, assetNode.Dependencies),
Builders<AssetNode>.Update.Set(fn => fn.Dependent, assetNode.Dependent)
));
}
break;
}
default:
break;
}
}
public void Delete<T>(T node) where T : AssetNode
{
switch (node)
{
case FolderNode folderNode:
{
var filter = Builders<FolderNode>.Filter.And(
Builders<FolderNode>.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<PackageNode>.Filter.And(
Builders<PackageNode>.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<AssetNode>.Filter.And(
Builders<AssetNode>.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<AssetNode>.Filter.And(
Builders<AssetNode>.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<PackageNode>.Filter.And(
Builders<PackageNode>.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<FolderNode>.Filter.And(
Builders<FolderNode>.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;
}
}
}