diff --git a/desktop/go.mod b/desktop/go.mod index 99ee19e..b40c4d3 100644 --- a/desktop/go.mod +++ b/desktop/go.mod @@ -8,7 +8,7 @@ require github.com/wailsapp/wails/v3 v3.0.0-alpha.7 require ( go.mau.fi/gomuks v0.3.1 - go.mau.fi/util v0.8.3 + go.mau.fi/util v0.8.4-0.20241217203137-4aa8973d6dbc ) require ( diff --git a/desktop/go.sum b/desktop/go.sum index b8447c2..360d1a8 100644 --- a/desktop/go.sum +++ b/desktop/go.sum @@ -160,8 +160,8 @@ github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -go.mau.fi/util v0.8.3 h1:sulhXtfquMrQjsOP67x9CzWVBYUwhYeoo8hNQIpCWZ4= -go.mau.fi/util v0.8.3/go.mod h1:c00Db8xog70JeIsEvhdHooylTkTkakgnAOsZ04hplQY= +go.mau.fi/util v0.8.4-0.20241217203137-4aa8973d6dbc h1:55919oheHZLQktzYU2z9KSJ5KHXq34dYedoGFfdUcsg= +go.mau.fi/util v0.8.4-0.20241217203137-4aa8973d6dbc/go.mod h1:c00Db8xog70JeIsEvhdHooylTkTkakgnAOsZ04hplQY= go.mau.fi/zeroconfig v0.1.3 h1:As9wYDKmktjmNZW5i1vn8zvJlmGKHeVxHVIBMXsm4kM= go.mau.fi/zeroconfig v0.1.3/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/go.mod b/go.mod index dc75c88..df727e6 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/tidwall/gjson v1.18.0 github.com/tidwall/sjson v1.2.5 github.com/yuin/goldmark v1.7.8 - go.mau.fi/util v0.8.3 + go.mau.fi/util v0.8.4-0.20241217203137-4aa8973d6dbc go.mau.fi/zeroconfig v0.1.3 golang.org/x/crypto v0.31.0 golang.org/x/image v0.23.0 diff --git a/go.sum b/go.sum index d42850a..c1e60de 100644 --- a/go.sum +++ b/go.sum @@ -63,8 +63,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -go.mau.fi/util v0.8.3 h1:sulhXtfquMrQjsOP67x9CzWVBYUwhYeoo8hNQIpCWZ4= -go.mau.fi/util v0.8.3/go.mod h1:c00Db8xog70JeIsEvhdHooylTkTkakgnAOsZ04hplQY= +go.mau.fi/util v0.8.4-0.20241217203137-4aa8973d6dbc h1:55919oheHZLQktzYU2z9KSJ5KHXq34dYedoGFfdUcsg= +go.mau.fi/util v0.8.4-0.20241217203137-4aa8973d6dbc/go.mod h1:c00Db8xog70JeIsEvhdHooylTkTkakgnAOsZ04hplQY= go.mau.fi/zeroconfig v0.1.3 h1:As9wYDKmktjmNZW5i1vn8zvJlmGKHeVxHVIBMXsm4kM= go.mau.fi/zeroconfig v0.1.3/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= diff --git a/pkg/hicli/events.go b/pkg/hicli/events.go index c3ee935..c46d661 100644 --- a/pkg/hicli/events.go +++ b/pkg/hicli/events.go @@ -44,9 +44,10 @@ func (c *SyncComplete) IsEmpty() bool { type SyncStatusType string const ( - SyncStatusOK SyncStatusType = "ok" - SyncStatusWaiting SyncStatusType = "waiting" - SyncStatusErrored SyncStatusType = "errored" + SyncStatusOK SyncStatusType = "ok" + SyncStatusWaiting SyncStatusType = "waiting" + SyncStatusErroring SyncStatusType = "erroring" + SyncStatusFailed SyncStatusType = "permanently-failed" ) type SyncStatus struct { diff --git a/pkg/hicli/hicli.go b/pkg/hicli/hicli.go index aa8e5e9..3b41577 100644 --- a/pkg/hicli/hicli.go +++ b/pkg/hicli/hicli.go @@ -252,7 +252,7 @@ func (h *HiClient) Sync() { log.Info().Msg("Starting syncing") err := h.Client.SyncWithContext(ctx) if err != nil && ctx.Err() == nil { - h.markSyncErrored(err) + h.markSyncErrored(err, true) log.Err(err).Msg("Fatal error in syncer") } else { h.SyncStatus.Store(syncWaiting) diff --git a/pkg/hicli/sync.go b/pkg/hicli/sync.go index b4aa257..2c014c1 100644 --- a/pkg/hicli/sync.go +++ b/pkg/hicli/sync.go @@ -39,13 +39,16 @@ type syncContext struct { evt *SyncComplete } -func (h *HiClient) markSyncErrored(err error) { +func (h *HiClient) markSyncErrored(err error, permanent bool) { stat := &SyncStatus{ - Type: SyncStatusErrored, + Type: SyncStatusErroring, Error: err.Error(), ErrorCount: h.syncErrors, LastSync: jsontime.UM(h.lastSync), } + if permanent { + stat.Type = SyncStatusFailed + } h.SyncStatus.Store(stat) h.EventHandler(stat) } diff --git a/pkg/hicli/syncwrap.go b/pkg/hicli/syncwrap.go index 5c14e88..3a07656 100644 --- a/pkg/hicli/syncwrap.go +++ b/pkg/hicli/syncwrap.go @@ -8,9 +8,11 @@ package hicli import ( "context" + "errors" "fmt" "time" + "github.com/mattn/go-sqlite3" "maunium.net/go/mautrix" "maunium.net/go/mautrix/id" ) @@ -37,11 +39,18 @@ func (h *hiSyncer) ProcessResponse(ctx context.Context, resp *mautrix.RespSync, if err != nil { return err } - err = c.DB.DoTxn(ctx, nil, func(ctx context.Context) error { - return c.processSyncResponse(ctx, resp, since) - }) - if err != nil { - return err + for i := 0; ; i++ { + err = c.DB.DoTxn(ctx, nil, func(ctx context.Context) error { + return c.processSyncResponse(ctx, resp, since) + }) + if errors.Is(err, sqlite3.ErrLocked) && i < 24 { + c.markSyncErrored(err, false) + continue + } else if err != nil { + return err + } else { + break + } } c.postProcessSyncResponse(ctx, resp, since) c.syncErrors = 0 @@ -56,7 +65,7 @@ func (h *hiSyncer) OnFailedSync(_ *mautrix.RespSync, err error) (time.Duration, if c.syncErrors > 5 { delay = max(time.Duration(c.syncErrors)*time.Second, 30*time.Second) } - c.markSyncErrored(err) + c.markSyncErrored(err, false) c.Log.Err(err).Dur("retry_in", delay).Msg("Sync failed") return delay, nil } diff --git a/web/src/api/types/hievents.ts b/web/src/api/types/hievents.ts index f4bc4ec..900478b 100644 --- a/web/src/api/types/hievents.ts +++ b/web/src/api/types/hievents.ts @@ -110,7 +110,7 @@ export interface ClientStateEvent extends BaseRPCCommand { } export interface SyncStatus { - type: "ok" | "waiting" | "errored" + type: "ok" | "waiting" | "erroring" | "permanently-failed" error?: string error_count: number last_sync?: number diff --git a/web/src/ui/MainScreen.tsx b/web/src/ui/MainScreen.tsx index 6a720b7..737c9d2 100644 --- a/web/src/ui/MainScreen.tsx +++ b/web/src/ui/MainScreen.tsx @@ -302,13 +302,17 @@ const MainScreen = () => { Waiting for first sync... } else if ( - syncStatus.type === "errored" + syncStatus.type === "erroring" && (syncStatus.error_count > 2 || (syncStatus.last_sync ?? 0) + SYNC_ERROR_HIDE_DELAY < Date.now()) ) { syncLoader =
Sync is failing
+ } else if (syncStatus.type === "permanently-failed") { + syncLoader =
+ Sync failed permanently +
} const renderedRoom = activeRoom ?? prevActiveRoom useEffect(() => {