mirror of
https://github.com/2dust/v2rayN.git
synced 2026-11-02 18:45: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);
|
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)
|
public async Task<int> InsertAsync(object model)
|
||||||
{
|
{
|
||||||
return await _dbAsync.InsertAsync(model);
|
return await _dbAsync.InsertAsync(model);
|
||||||
|
|||||||
@@ -39,15 +39,14 @@ public class ProfileExManager
|
|||||||
{
|
{
|
||||||
if (indexId.IsNotEmpty())
|
if (indexId.IsNotEmpty())
|
||||||
{
|
{
|
||||||
//Speed tests touch this from many threads; duplicates are harmless here since
|
//Speed tests touch this from many threads; the save loop deduplicates IDs.
|
||||||
//the save loop just writes the same row more than once
|
|
||||||
_queIndexIds.Enqueue(indexId);
|
_queIndexIds.Enqueue(indexId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveQueueIndexIds()
|
private async Task SaveQueueIndexIds()
|
||||||
{
|
{
|
||||||
var lstIds = new List<string>();
|
var lstIds = new HashSet<string>();
|
||||||
while (_queIndexIds.TryDequeue(out var id))
|
while (_queIndexIds.TryDequeue(out var id))
|
||||||
{
|
{
|
||||||
lstIds.Add(id);
|
lstIds.Add(id);
|
||||||
@@ -55,39 +54,25 @@ public class ProfileExManager
|
|||||||
|
|
||||||
if (lstIds.Count > 0)
|
if (lstIds.Count > 0)
|
||||||
{
|
{
|
||||||
var lstExists = await SQLiteHelper.Instance.TableAsync<ProfileExItem>().ToListAsync();
|
List<ProfileExItem> lstSaves = [];
|
||||||
List<ProfileExItem> lstInserts = [];
|
|
||||||
List<ProfileExItem> lstUpdates = [];
|
|
||||||
|
|
||||||
foreach (var id in lstIds)
|
foreach (var id in lstIds)
|
||||||
{
|
{
|
||||||
var item = lstExists.FirstOrDefault(t => t.IndexId == id);
|
|
||||||
var itemNew = _lstProfileEx?.FirstOrDefault(t => t.IndexId == id);
|
var itemNew = _lstProfileEx?.FirstOrDefault(t => t.IndexId == id);
|
||||||
if (itemNew is null)
|
if (itemNew is null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item is not null)
|
lstSaves.Add(itemNew);
|
||||||
{
|
|
||||||
lstUpdates.Add(itemNew);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lstInserts.Add(itemNew);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (lstInserts.Count > 0)
|
if (lstSaves.Count > 0)
|
||||||
{
|
{
|
||||||
await SQLiteHelper.Instance.InsertAllAsync(lstInserts);
|
//Another save may have inserted these rows since the queue was drained.
|
||||||
}
|
await SQLiteHelper.Instance.ReplaceAllAsync(lstSaves);
|
||||||
|
|
||||||
if (lstUpdates.Count > 0)
|
|
||||||
{
|
|
||||||
await SQLiteHelper.Instance.UpdateAllAsync(lstUpdates);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
Reference in New Issue
Block a user