Skip to content

Commit 3a3da51

Browse files
authored
Merge pull request #1763 from Flow-Launcher/atomic_setting_save
Atomic Save for Setting
2 parents 9be71e8 + f517343 commit 3a3da51

File tree

4 files changed

+56
-39
lines changed

4 files changed

+56
-39
lines changed

.github/actions/spelling/expect.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ TobiasSekan
6262
Img
6363
img
6464
resx
65+
bak
66+
tmp
6567
directx
6668
mvvm
6769
dlg
@@ -85,4 +87,4 @@ searchplugin
8587
Noresult
8688
wpftk
8789
mkv
88-
flac
90+
flac

Flow.Launcher.Infrastructure/Helper.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System;
1+
#nullable enable
2+
3+
using System;
24
using System.IO;
35
using System.Runtime.CompilerServices;
46
using System.Text.Json;
@@ -16,7 +18,7 @@ static Helper()
1618
/// <summary>
1719
/// http://www.yinwang.org/blog-cn/2015/11/21/programming-philosophy
1820
/// </summary>
19-
public static T NonNull<T>(this T obj)
21+
public static T NonNull<T>(this T? obj)
2022
{
2123
if (obj == null)
2224
{
Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System;
1+
#nullable enable
2+
using System;
23
using System.Globalization;
34
using System.IO;
45
using System.Text.Json;
@@ -11,62 +12,73 @@ namespace Flow.Launcher.Infrastructure.Storage
1112
/// </summary>
1213
public class JsonStorage<T> where T : new()
1314
{
14-
protected T _data;
15+
protected T? Data;
1516
// need a new directory name
1617
public const string DirectoryName = "Settings";
1718
public const string FileSuffix = ".json";
18-
public string FilePath { get; set; }
19-
public string DirectoryPath { get; set; }
19+
protected string FilePath { get; init; } = null!;
20+
private string TempFilePath => $"{FilePath}.tmp";
21+
private string BackupFilePath => $"{FilePath}.bak";
22+
protected string DirectoryPath { get; init; } = null!;
2023

2124

2225
public T Load()
2326
{
27+
string? serialized = null;
28+
2429
if (File.Exists(FilePath))
2530
{
26-
var serialized = File.ReadAllText(FilePath);
27-
if (!string.IsNullOrWhiteSpace(serialized))
31+
serialized = File.ReadAllText(FilePath);
32+
}
33+
34+
if (!string.IsNullOrEmpty(serialized))
35+
{
36+
try
2837
{
29-
Deserialize(serialized);
38+
Data = JsonSerializer.Deserialize<T>(serialized)?? TryLoadBackup() ?? LoadDefault();
3039
}
31-
else
40+
catch (JsonException)
3241
{
33-
LoadDefault();
42+
Data = TryLoadBackup() ?? LoadDefault();
3443
}
3544
}
3645
else
3746
{
38-
LoadDefault();
47+
Data = TryLoadBackup() ?? LoadDefault();
3948
}
40-
return _data.NonNull();
49+
return Data.NonNull();
4150
}
4251

43-
private void Deserialize(string serialized)
52+
private T LoadDefault()
4453
{
45-
try
46-
{
47-
_data = JsonSerializer.Deserialize<T>(serialized);
48-
}
49-
catch (JsonException e)
54+
if (File.Exists(FilePath))
5055
{
51-
LoadDefault();
52-
Log.Exception($"|JsonStorage.Deserialize|Deserialize error for json <{FilePath}>", e);
56+
BackupOriginFile();
5357
}
5458

55-
if (_data == null)
56-
{
57-
LoadDefault();
58-
}
59+
return new T();
5960
}
6061

61-
private void LoadDefault()
62+
private T? TryLoadBackup()
6263
{
63-
if (File.Exists(FilePath))
64+
if (!File.Exists(BackupFilePath))
65+
return default;
66+
67+
try
6468
{
65-
BackupOriginFile();
69+
var data = JsonSerializer.Deserialize<T>(File.ReadAllText(BackupFilePath));
70+
if (data != null)
71+
{
72+
Log.Info($"|JsonStorage.Load|Failed to load settings.json, {BackupFilePath} restored successfully");
73+
File.Replace(BackupFilePath, FilePath, null);
74+
return data;
75+
}
76+
return default;
77+
}
78+
catch (JsonException)
79+
{
80+
return default;
6681
}
67-
68-
_data = new T();
69-
Save();
7082
}
7183

7284
private void BackupOriginFile()
@@ -82,13 +94,14 @@ private void BackupOriginFile()
8294

8395
public void Save()
8496
{
85-
string serialized = JsonSerializer.Serialize(_data, new JsonSerializerOptions() { WriteIndented = true });
97+
string serialized = JsonSerializer.Serialize(Data, new JsonSerializerOptions
98+
{
99+
WriteIndented = true
100+
});
86101

87-
File.WriteAllText(FilePath, serialized);
102+
File.WriteAllText(TempFilePath, serialized);
103+
File.Replace(TempFilePath, FilePath, BackupFilePath);
104+
File.Delete(TempFilePath);
88105
}
89106
}
90-
91-
[Obsolete("Deprecated as of Flow Launcher v1.8.0, on 2021.06.21. " +
92-
"This is used only for Everything plugin v1.4.9 or below backwards compatibility")]
93-
public class JsonStrorage<T> : JsonStorage<T> where T : new() { }
94107
}

Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public PluginJsonStorage()
1818

1919
public PluginJsonStorage(T data) : this()
2020
{
21-
_data = data;
21+
Data = data;
2222
}
2323
}
2424
}

0 commit comments

Comments
 (0)