mirror of
https://github.com/MikuLeaks/MikuSB.git
synced 2026-06-04 16:23:58 +00:00
fix racing between AutoSave and process exit
This commit is contained in:
@@ -14,7 +14,10 @@ public class DatabaseHelper
|
||||
public static readonly ConcurrentDictionary<int, List<BaseDatabaseDataHelper>> UidInstanceMap = [];
|
||||
public static readonly List<int> ToSaveUidList = [];
|
||||
public static long LastSaveTick = DateTime.UtcNow.Ticks;
|
||||
public static Thread? SaveThread;
|
||||
|
||||
private static int _saving = 0;
|
||||
private static Task? _saveTask;
|
||||
private static CancellationTokenSource? _cts;
|
||||
public static bool LoadAccount;
|
||||
public static bool LoadAllData;
|
||||
|
||||
@@ -80,16 +83,8 @@ public class DatabaseHelper
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
|
||||
LastSaveTick = DateTime.UtcNow.Ticks;
|
||||
|
||||
SaveThread = new Thread(async () =>
|
||||
{
|
||||
while (true) {
|
||||
CalcSaveDatabase();
|
||||
await Task.Delay(100);
|
||||
}
|
||||
});
|
||||
SaveThread.Start();
|
||||
_cts = new CancellationTokenSource();
|
||||
_saveTask = RunAutoSave(_cts.Token);
|
||||
|
||||
LoadAllData = true;
|
||||
}
|
||||
@@ -252,6 +247,35 @@ public class DatabaseHelper
|
||||
ToSaveUidList.RemoveAll(x => x == key);
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
_cts?.Cancel();
|
||||
}
|
||||
|
||||
public static async Task WaitAsync()
|
||||
{
|
||||
if (_saveTask != null)
|
||||
await _saveTask;
|
||||
}
|
||||
|
||||
private static async Task RunAutoSave(CancellationToken token)
|
||||
{
|
||||
LastSaveTick = DateTime.UtcNow.Ticks;
|
||||
try
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
CalcSaveDatabase();
|
||||
await Task.Delay(100, token);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// exit normally
|
||||
// Console.WriteLine($"RunAutoSave exit! - OperationCanceledException");
|
||||
}
|
||||
}
|
||||
|
||||
// Auto save per 5 min
|
||||
public static void CalcSaveDatabase()
|
||||
{
|
||||
@@ -261,6 +285,10 @@ public class DatabaseHelper
|
||||
|
||||
public static void SaveDatabase()
|
||||
{
|
||||
// ensure only one SaveDatabase() runnig
|
||||
if (Interlocked.Exchange(ref _saving, 1) == 1)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var prev = DateTime.Now;
|
||||
@@ -285,11 +313,18 @@ public class DatabaseHelper
|
||||
Math.Round(t, 2).ToString(CultureInfo.InvariantCulture)));
|
||||
|
||||
ToSaveUidList.Clear();
|
||||
|
||||
// Thread.Sleep(5000); // for test if saving process taking too long
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error("An error occurred while saving the database", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// release lock
|
||||
Volatile.Write(ref _saving, 0);
|
||||
}
|
||||
|
||||
LastSaveTick = DateTime.UtcNow.Ticks;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class MikuSB
|
||||
|
||||
await consoleTask;
|
||||
|
||||
ProcessExit(Volatile.Read(ref _exitCode));
|
||||
await ProcessExit(Volatile.Read(ref _exitCode));
|
||||
}
|
||||
|
||||
#region Exit
|
||||
@@ -96,11 +96,15 @@ public class MikuSB
|
||||
_cts.Cancel();
|
||||
}
|
||||
|
||||
private static void ProcessExit(int exitCode)
|
||||
private static async Task ProcessExit(int exitCode)
|
||||
{
|
||||
SocketListener.Connections.Values.ToList().ForEach(x => x.Stop(true));
|
||||
DatabaseHelper.SaveThread?.Interrupt();
|
||||
DatabaseHelper.SaveDatabase();
|
||||
|
||||
DatabaseHelper.Stop(); // notify stop
|
||||
await DatabaseHelper.WaitAsync(); // wait AutoSave thread exit
|
||||
|
||||
DatabaseHelper.SaveDatabase(); // final flush
|
||||
|
||||
Environment.Exit(exitCode);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user