Files
v2rayN/v2rayN/ServiceLib/Manager/ProfileExManager.cs
T
2026-11-02 09:26:34 +08:00

195 lines
4.8 KiB
C#

namespace ServiceLib.Manager;
public class ProfileExManager
{
private static readonly Lazy<ProfileExManager> _instance = new(() => new());
private ConcurrentBag<ProfileExItem> _lstProfileEx = [];
private readonly ConcurrentQueue<string> _queIndexIds = new();
private readonly Lock _profileExLock = new();
public static ProfileExManager Instance => _instance.Value;
private static readonly string _tag = "ProfileExHandler";
public ProfileExManager()
{
//Init();
}
public async Task Init()
{
await InitData();
}
public async Task<ConcurrentBag<ProfileExItem>> GetProfileExs()
{
return await Task.FromResult(_lstProfileEx);
}
private async Task InitData()
{
await SQLiteHelper.Instance.ExecuteAsync($"delete from ProfileExItem where indexId not in ( select indexId from ProfileItem )");
var lstProfileEx = new ConcurrentBag<ProfileExItem>(await SQLiteHelper.Instance.TableAsync<ProfileExItem>().ToListAsync());
lock (_profileExLock)
{
_lstProfileEx = lstProfileEx;
}
}
private void IndexIdEnqueue(string indexId)
{
if (indexId.IsNotEmpty())
{
//Speed tests touch this from many threads; the save loop deduplicates IDs.
_queIndexIds.Enqueue(indexId);
}
}
private async Task SaveQueueIndexIds()
{
var lstIds = new HashSet<string>();
while (_queIndexIds.TryDequeue(out var id))
{
lstIds.Add(id);
}
if (lstIds.Count > 0)
{
List<ProfileExItem> lstSaves = [];
foreach (var id in lstIds)
{
var itemNew = _lstProfileEx?.FirstOrDefault(t => t.IndexId == id);
if (itemNew is null)
{
continue;
}
lstSaves.Add(itemNew);
}
try
{
if (lstSaves.Count > 0)
{
//Another save may have inserted these rows since the queue was drained.
await SQLiteHelper.Instance.ReplaceAllAsync(lstSaves);
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
}
private ProfileExItem AddProfileEx(string indexId)
{
var profileEx = new ProfileExItem()
{
IndexId = indexId,
Delay = 0,
Speed = 0,
Sort = 0,
Message = string.Empty
};
_lstProfileEx.Add(profileEx);
IndexIdEnqueue(indexId);
return profileEx;
}
private ProfileExItem GetProfileExItem(string? indexId)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
if (profileEx is not null)
{
return profileEx;
}
lock (_profileExLock)
{
profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
return profileEx ?? AddProfileEx(indexId);
}
}
public async Task ClearAll()
{
await SQLiteHelper.Instance.ExecuteAsync($"delete from ProfileExItem ");
lock (_profileExLock)
{
_lstProfileEx = [];
}
}
public async Task SaveTo()
{
try
{
await SaveQueueIndexIds();
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public void SetTestDelay(string indexId, int delay)
{
var profileEx = GetProfileExItem(indexId);
profileEx.Delay = delay;
IndexIdEnqueue(indexId);
}
public void SetTestSpeed(string indexId, decimal speed)
{
var profileEx = GetProfileExItem(indexId);
profileEx.Speed = speed;
IndexIdEnqueue(indexId);
}
public void SetTestMessage(string indexId, string message)
{
var profileEx = GetProfileExItem(indexId);
profileEx.Message = message;
IndexIdEnqueue(indexId);
}
public void SetTestIpInfo(string indexId, string ipInfo)
{
var profileEx = GetProfileExItem(indexId);
profileEx.IpInfo = ipInfo;
IndexIdEnqueue(indexId);
}
public void SetSort(string indexId, int sort)
{
var profileEx = GetProfileExItem(indexId);
profileEx.Sort = sort;
IndexIdEnqueue(indexId);
}
public int GetSort(string indexId)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
if (profileEx == null)
{
return 0;
}
return profileEx.Sort;
}
public int GetMaxSort()
{
if (_lstProfileEx.Count <= 0)
{
return 0;
}
return _lstProfileEx.Max(t => t?.Sort ?? 0);
}
}