forked from Mirrors/gomuks
hicli/sync: don't fail sync if database is locked
This commit is contained in:
parent
0b1d5cd354
commit
29b787f94a
10 changed files with 37 additions and 20 deletions
|
@ -8,7 +8,7 @@ require github.com/wailsapp/wails/v3 v3.0.0-alpha.7
|
||||||
|
|
||||||
require (
|
require (
|
||||||
go.mau.fi/gomuks v0.3.1
|
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 (
|
require (
|
||||||
|
|
|
@ -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.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 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
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.4-0.20241217203137-4aa8973d6dbc h1:55919oheHZLQktzYU2z9KSJ5KHXq34dYedoGFfdUcsg=
|
||||||
go.mau.fi/util v0.8.3/go.mod h1:c00Db8xog70JeIsEvhdHooylTkTkakgnAOsZ04hplQY=
|
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 h1:As9wYDKmktjmNZW5i1vn8zvJlmGKHeVxHVIBMXsm4kM=
|
||||||
go.mau.fi/zeroconfig v0.1.3/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70=
|
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=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -17,7 +17,7 @@ require (
|
||||||
github.com/tidwall/gjson v1.18.0
|
github.com/tidwall/gjson v1.18.0
|
||||||
github.com/tidwall/sjson v1.2.5
|
github.com/tidwall/sjson v1.2.5
|
||||||
github.com/yuin/goldmark v1.7.8
|
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
|
go.mau.fi/zeroconfig v0.1.3
|
||||||
golang.org/x/crypto v0.31.0
|
golang.org/x/crypto v0.31.0
|
||||||
golang.org/x/image v0.23.0
|
golang.org/x/image v0.23.0
|
||||||
|
|
4
go.sum
4
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/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 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
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.4-0.20241217203137-4aa8973d6dbc h1:55919oheHZLQktzYU2z9KSJ5KHXq34dYedoGFfdUcsg=
|
||||||
go.mau.fi/util v0.8.3/go.mod h1:c00Db8xog70JeIsEvhdHooylTkTkakgnAOsZ04hplQY=
|
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 h1:As9wYDKmktjmNZW5i1vn8zvJlmGKHeVxHVIBMXsm4kM=
|
||||||
go.mau.fi/zeroconfig v0.1.3/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70=
|
go.mau.fi/zeroconfig v0.1.3/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70=
|
||||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||||
|
|
|
@ -44,9 +44,10 @@ func (c *SyncComplete) IsEmpty() bool {
|
||||||
type SyncStatusType string
|
type SyncStatusType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SyncStatusOK SyncStatusType = "ok"
|
SyncStatusOK SyncStatusType = "ok"
|
||||||
SyncStatusWaiting SyncStatusType = "waiting"
|
SyncStatusWaiting SyncStatusType = "waiting"
|
||||||
SyncStatusErrored SyncStatusType = "errored"
|
SyncStatusErroring SyncStatusType = "erroring"
|
||||||
|
SyncStatusFailed SyncStatusType = "permanently-failed"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SyncStatus struct {
|
type SyncStatus struct {
|
||||||
|
|
|
@ -252,7 +252,7 @@ func (h *HiClient) Sync() {
|
||||||
log.Info().Msg("Starting syncing")
|
log.Info().Msg("Starting syncing")
|
||||||
err := h.Client.SyncWithContext(ctx)
|
err := h.Client.SyncWithContext(ctx)
|
||||||
if err != nil && ctx.Err() == nil {
|
if err != nil && ctx.Err() == nil {
|
||||||
h.markSyncErrored(err)
|
h.markSyncErrored(err, true)
|
||||||
log.Err(err).Msg("Fatal error in syncer")
|
log.Err(err).Msg("Fatal error in syncer")
|
||||||
} else {
|
} else {
|
||||||
h.SyncStatus.Store(syncWaiting)
|
h.SyncStatus.Store(syncWaiting)
|
||||||
|
|
|
@ -39,13 +39,16 @@ type syncContext struct {
|
||||||
evt *SyncComplete
|
evt *SyncComplete
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HiClient) markSyncErrored(err error) {
|
func (h *HiClient) markSyncErrored(err error, permanent bool) {
|
||||||
stat := &SyncStatus{
|
stat := &SyncStatus{
|
||||||
Type: SyncStatusErrored,
|
Type: SyncStatusErroring,
|
||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
ErrorCount: h.syncErrors,
|
ErrorCount: h.syncErrors,
|
||||||
LastSync: jsontime.UM(h.lastSync),
|
LastSync: jsontime.UM(h.lastSync),
|
||||||
}
|
}
|
||||||
|
if permanent {
|
||||||
|
stat.Type = SyncStatusFailed
|
||||||
|
}
|
||||||
h.SyncStatus.Store(stat)
|
h.SyncStatus.Store(stat)
|
||||||
h.EventHandler(stat)
|
h.EventHandler(stat)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,11 @@ package hicli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mattn/go-sqlite3"
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
)
|
)
|
||||||
|
@ -37,11 +39,18 @@ func (h *hiSyncer) ProcessResponse(ctx context.Context, resp *mautrix.RespSync,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = c.DB.DoTxn(ctx, nil, func(ctx context.Context) error {
|
for i := 0; ; i++ {
|
||||||
return c.processSyncResponse(ctx, resp, since)
|
err = c.DB.DoTxn(ctx, nil, func(ctx context.Context) error {
|
||||||
})
|
return c.processSyncResponse(ctx, resp, since)
|
||||||
if err != nil {
|
})
|
||||||
return err
|
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.postProcessSyncResponse(ctx, resp, since)
|
||||||
c.syncErrors = 0
|
c.syncErrors = 0
|
||||||
|
@ -56,7 +65,7 @@ func (h *hiSyncer) OnFailedSync(_ *mautrix.RespSync, err error) (time.Duration,
|
||||||
if c.syncErrors > 5 {
|
if c.syncErrors > 5 {
|
||||||
delay = max(time.Duration(c.syncErrors)*time.Second, 30*time.Second)
|
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")
|
c.Log.Err(err).Dur("retry_in", delay).Msg("Sync failed")
|
||||||
return delay, nil
|
return delay, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ export interface ClientStateEvent extends BaseRPCCommand<ClientState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SyncStatus {
|
export interface SyncStatus {
|
||||||
type: "ok" | "waiting" | "errored"
|
type: "ok" | "waiting" | "erroring" | "permanently-failed"
|
||||||
error?: string
|
error?: string
|
||||||
error_count: number
|
error_count: number
|
||||||
last_sync?: number
|
last_sync?: number
|
||||||
|
|
|
@ -302,13 +302,17 @@ const MainScreen = () => {
|
||||||
Waiting for first sync...
|
Waiting for first sync...
|
||||||
</div>
|
</div>
|
||||||
} else if (
|
} else if (
|
||||||
syncStatus.type === "errored"
|
syncStatus.type === "erroring"
|
||||||
&& (syncStatus.error_count > 2 || (syncStatus.last_sync ?? 0) + SYNC_ERROR_HIDE_DELAY < Date.now())
|
&& (syncStatus.error_count > 2 || (syncStatus.last_sync ?? 0) + SYNC_ERROR_HIDE_DELAY < Date.now())
|
||||||
) {
|
) {
|
||||||
syncLoader = <div className="sync-status errored" title={syncStatus.error}>
|
syncLoader = <div className="sync-status errored" title={syncStatus.error}>
|
||||||
<SyncLoader color="var(--error-color)"/>
|
<SyncLoader color="var(--error-color)"/>
|
||||||
Sync is failing
|
Sync is failing
|
||||||
</div>
|
</div>
|
||||||
|
} else if (syncStatus.type === "permanently-failed") {
|
||||||
|
syncLoader = <div className="sync-status errored" title={syncStatus.error}>
|
||||||
|
Sync failed permanently
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
const renderedRoom = activeRoom ?? prevActiveRoom
|
const renderedRoom = activeRoom ?? prevActiveRoom
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue