From 3999d1223c262fc4e62512b949591f731563a4a7 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Thu, 4 Jul 2024 19:31:48 +0800 Subject: [PATCH 1/2] Backend: make InvalidJson show the nonJSON content It might be interesting to see it, for debugging purposes. --- src/GWallet.Backend/Exceptions.fs | 2 +- src/GWallet.Backend/Marshalling.fs | 2 +- src/GWallet.Frontend.Console/Program.fs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/GWallet.Backend/Exceptions.fs b/src/GWallet.Backend/Exceptions.fs index aa5b2fde7..a7b2172b8 100644 --- a/src/GWallet.Backend/Exceptions.fs +++ b/src/GWallet.Backend/Exceptions.fs @@ -23,7 +23,7 @@ exception AccountAlreadyAdded exception InvalidDestinationAddress of msg: string -exception InvalidJson +exception InvalidJson of content: string exception TransactionAlreadySigned exception TransactionNotSignedYet diff --git a/src/GWallet.Backend/Marshalling.fs b/src/GWallet.Backend/Marshalling.fs index 57a4c2dc2..81c57c368 100644 --- a/src/GWallet.Backend/Marshalling.fs +++ b/src/GWallet.Backend/Marshalling.fs @@ -175,7 +175,7 @@ module Marshalling = if (String.IsNullOrWhiteSpace(json)) then raise (ArgumentException("empty or whitespace json", "json")) if not (IsValidJson json) then - raise <| InvalidJson + raise <| InvalidJson json let deserialized = try diff --git a/src/GWallet.Frontend.Console/Program.fs b/src/GWallet.Frontend.Console/Program.fs index a337961f6..391d52fce 100644 --- a/src/GWallet.Frontend.Console/Program.fs +++ b/src/GWallet.Frontend.Console/Program.fs @@ -246,7 +246,7 @@ module Program = Marshalling.Deserialize watchWalletInfoJson |> Some with - | InvalidJson -> + | InvalidJson _content -> None match watchWalletInfoOpt with From 7a0b5d52ce01d0efa257a1a66fafee82bb8be113 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Thu, 4 Jul 2024 20:11:51 +0800 Subject: [PATCH 2/2] Backend/Caching: save(&restore) .bak files We've had one occassion already where a wallet instance was crashing at start somehow finding invalid JSON. In this case we can just discard the data and recreate (because it's cache) however we can do better and just use backups. --- src/GWallet.Backend/Caching.fs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/GWallet.Backend/Caching.fs b/src/GWallet.Backend/Caching.fs index 2736032d3..5d7825a17 100644 --- a/src/GWallet.Backend/Caching.fs +++ b/src/GWallet.Backend/Caching.fs @@ -132,7 +132,20 @@ module Caching = Object.ReferenceEquals(x, null) let private LoadFromDisk (files: CacheFiles): bool*CachedNetworkData*ServerRanking = - let maybeNetworkData = LoadFromDiskInternal files.CachedNetworkData + let networkDataBackup = SPrintF1 "%s.bak" files.CachedNetworkData.FullName |> FileInfo + let maybeNetworkData = + try + LoadFromDiskInternal files.CachedNetworkData + with + // data become corrupted somehow + | InvalidJson _ -> + if networkDataBackup.Exists then + let res = LoadFromDiskInternal networkDataBackup + networkDataBackup.CopyTo(files.CachedNetworkData.FullName, true) |> ignore + res + else + reraise() + let maybeFirstRun,resultingNetworkData = match maybeNetworkData with | None -> @@ -142,13 +155,27 @@ module Caching = Infrastructure.LogError droppedCachedMsgWarning true,CachedNetworkData.Empty else + files.CachedNetworkData.CopyTo(networkDataBackup.FullName, true) |> ignore false,networkData - let maybeServerStats = LoadFromDiskInternal files.ServerStats + let serverStatsBackup = SPrintF1 "%s.bak" files.ServerStats.FullName |> FileInfo + let maybeServerStats = + try + LoadFromDiskInternal files.ServerStats + with + // data become corrupted somehow + | InvalidJson _ -> + if serverStatsBackup.Exists then + let res = LoadFromDiskInternal serverStatsBackup + serverStatsBackup.CopyTo(files.CachedNetworkData.FullName, true) |> ignore + res + else + reraise() match maybeServerStats with | None -> maybeFirstRun,resultingNetworkData,Map.empty | Some serverStats -> + files.ServerStats.CopyTo(serverStatsBackup.FullName, true) |> ignore false,resultingNetworkData,serverStats let rec private MergeRatesInternal (oldMap: Map<'K, CachedValue<'V>>)