mirror of
https://github.com/2dust/v2rayN.git
synced 2026-11-02 10:35:00 +03:00
fix: persist repeated profile test results (#10466)
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
namespace ServiceLib.Tests.Manager;
|
||||
|
||||
public class ProfileExManagerPersistenceTests
|
||||
{
|
||||
[Test]
|
||||
public async Task SaveTo_NewProfilesWithRepeatedResults_ShouldPersistEveryProfile()
|
||||
{
|
||||
SQLiteHelper.Instance.CreateTable<ProfileExItem>();
|
||||
var manager = new ProfileExManager();
|
||||
var ids = Enumerable.Range(0, 3).Select(_ => Guid.NewGuid().ToString("N")).ToArray();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var id in ids)
|
||||
{
|
||||
manager.SetTestDelay(id, 42);
|
||||
manager.SetTestSpeed(id, 12.5m);
|
||||
manager.SetTestMessage(id, "completed");
|
||||
manager.SetTestIpInfo(id, "192.0.2.1");
|
||||
manager.SetSort(id, 7);
|
||||
}
|
||||
|
||||
await manager.SaveTo();
|
||||
|
||||
foreach (var id in ids)
|
||||
{
|
||||
var saved = await SQLiteHelper.Instance.TableAsync<ProfileExItem>()
|
||||
.Where(t => t.IndexId == id).ToListAsync();
|
||||
await saved.Count.Should().BeEqualTo(1);
|
||||
await saved[0].Delay.Should().BeEqualTo(42);
|
||||
await saved[0].Speed.Should().BeEqualTo(12.5m);
|
||||
await saved[0].Message.Should().BeEqualTo("completed");
|
||||
await saved[0].IpInfo.Should().BeEqualTo("192.0.2.1");
|
||||
await saved[0].Sort.Should().BeEqualTo(7);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var id in ids)
|
||||
{
|
||||
await SQLiteHelper.Instance.DeleteAsync(new ProfileExItem { IndexId = id });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SaveTo_MixedNewAndExistingProfiles_ShouldInsertAndUpdateResults()
|
||||
{
|
||||
SQLiteHelper.Instance.CreateTable<ProfileExItem>();
|
||||
var manager = new ProfileExManager();
|
||||
var existingId = Guid.NewGuid().ToString("N");
|
||||
var newId = Guid.NewGuid().ToString("N");
|
||||
|
||||
try
|
||||
{
|
||||
await SQLiteHelper.Instance.InsertAsync(new ProfileExItem
|
||||
{
|
||||
IndexId = existingId,
|
||||
Delay = 1,
|
||||
Speed = 2,
|
||||
});
|
||||
manager.SetTestDelay(existingId, 100);
|
||||
manager.SetTestSpeed(existingId, 20);
|
||||
manager.SetTestDelay(newId, 200);
|
||||
manager.SetTestIpInfo(newId, "192.0.2.2");
|
||||
|
||||
await manager.SaveTo();
|
||||
|
||||
var existing = await SQLiteHelper.Instance.TableAsync<ProfileExItem>()
|
||||
.Where(t => t.IndexId == existingId).FirstAsync();
|
||||
await existing.Delay.Should().BeEqualTo(100);
|
||||
await existing.Speed.Should().BeEqualTo(20m);
|
||||
var inserted = await SQLiteHelper.Instance.TableAsync<ProfileExItem>()
|
||||
.Where(t => t.IndexId == newId).ToListAsync();
|
||||
await inserted.Count.Should().BeEqualTo(1);
|
||||
await inserted[0].Delay.Should().BeEqualTo(200);
|
||||
await inserted[0].IpInfo.Should().BeEqualTo("192.0.2.2");
|
||||
|
||||
manager.SetTestDelay(newId, 300);
|
||||
await manager.SaveTo();
|
||||
var updated = await SQLiteHelper.Instance.TableAsync<ProfileExItem>()
|
||||
.Where(t => t.IndexId == newId).FirstAsync();
|
||||
await updated.Delay.Should().BeEqualTo(300);
|
||||
await updated.IpInfo.Should().BeEqualTo("192.0.2.2");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await SQLiteHelper.Instance.DeleteAsync(new ProfileExItem { IndexId = existingId });
|
||||
await SQLiteHelper.Instance.DeleteAsync(new ProfileExItem { IndexId = newId });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,11 @@ public sealed class SQLiteHelper
|
||||
return await _dbAsync.InsertAllAsync(models, runInTransaction: true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<int> ReplaceAllAsync(IEnumerable models)
|
||||
{
|
||||
return await _dbAsync.InsertAllAsync(models, extra: "OR REPLACE", runInTransaction: true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<int> InsertAsync(object model)
|
||||
{
|
||||
return await _dbAsync.InsertAsync(model);
|
||||
|
||||
@@ -39,15 +39,14 @@ public class ProfileExManager
|
||||
{
|
||||
if (indexId.IsNotEmpty())
|
||||
{
|
||||
//Speed tests touch this from many threads; duplicates are harmless here since
|
||||
//the save loop just writes the same row more than once
|
||||
//Speed tests touch this from many threads; the save loop deduplicates IDs.
|
||||
_queIndexIds.Enqueue(indexId);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveQueueIndexIds()
|
||||
{
|
||||
var lstIds = new List<string>();
|
||||
var lstIds = new HashSet<string>();
|
||||
while (_queIndexIds.TryDequeue(out var id))
|
||||
{
|
||||
lstIds.Add(id);
|
||||
@@ -55,39 +54,25 @@ public class ProfileExManager
|
||||
|
||||
if (lstIds.Count > 0)
|
||||
{
|
||||
var lstExists = await SQLiteHelper.Instance.TableAsync<ProfileExItem>().ToListAsync();
|
||||
List<ProfileExItem> lstInserts = [];
|
||||
List<ProfileExItem> lstUpdates = [];
|
||||
List<ProfileExItem> lstSaves = [];
|
||||
|
||||
foreach (var id in lstIds)
|
||||
{
|
||||
var item = lstExists.FirstOrDefault(t => t.IndexId == id);
|
||||
var itemNew = _lstProfileEx?.FirstOrDefault(t => t.IndexId == id);
|
||||
if (itemNew is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item is not null)
|
||||
{
|
||||
lstUpdates.Add(itemNew);
|
||||
}
|
||||
else
|
||||
{
|
||||
lstInserts.Add(itemNew);
|
||||
}
|
||||
lstSaves.Add(itemNew);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (lstInserts.Count > 0)
|
||||
if (lstSaves.Count > 0)
|
||||
{
|
||||
await SQLiteHelper.Instance.InsertAllAsync(lstInserts);
|
||||
}
|
||||
|
||||
if (lstUpdates.Count > 0)
|
||||
{
|
||||
await SQLiteHelper.Instance.UpdateAllAsync(lstUpdates);
|
||||
//Another save may have inserted these rows since the queue was drained.
|
||||
await SQLiteHelper.Instance.ReplaceAllAsync(lstSaves);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
Reference in New Issue
Block a user