Make sync status non-blocking

This commit is contained in:
Mikhail Chusavitin
2026-03-17 18:34:28 +03:00
parent a054fc7564
commit b0a106415f
4 changed files with 78 additions and 78 deletions

View File

@@ -78,41 +78,18 @@ type SyncReadinessResponse struct {
// GetStatus returns current sync status
// GET /api/sync/status
func (h *SyncHandler) GetStatus(c *gin.Context) {
// Check online status by pinging MariaDB
isOnline := h.checkOnline()
// Get sync times
connStatus := h.connMgr.GetStatus()
isOnline := connStatus.IsConnected && strings.TrimSpace(connStatus.LastError) == ""
lastComponentSync := h.localDB.GetComponentSyncTime()
lastPricelistSync := h.localDB.GetLastSyncTime()
// Get counts
componentsCount := h.localDB.CountLocalComponents()
pricelistsCount := h.localDB.CountLocalPricelists()
// Get server pricelist count if online
serverPricelists := 0
needPricelistSync := false
lastPricelistAttemptAt := h.localDB.GetLastPricelistSyncAttemptAt()
lastPricelistSyncStatus := h.localDB.GetLastPricelistSyncStatus()
lastPricelistSyncError := h.localDB.GetLastPricelistSyncError()
hasIncompleteServerSync := false
knownServerChangesMissing := false
if isOnline {
status, err := h.syncService.GetStatus()
if err == nil {
serverPricelists = status.ServerPricelists
needPricelistSync = status.NeedsSync
lastPricelistAttemptAt = status.LastAttemptAt
lastPricelistSyncStatus = status.LastSyncStatus
lastPricelistSyncError = status.LastSyncError
hasIncompleteServerSync = status.IncompleteServerSync
knownServerChangesMissing = status.KnownServerChangesMiss
}
}
// Check if component sync is needed (older than 24 hours)
hasFailedSync := strings.EqualFold(lastPricelistSyncStatus, "failed")
needComponentSync := h.localDB.NeedComponentSync(24)
readiness := h.getReadinessCached(10 * time.Second)
readiness := h.getReadinessLocal()
c.JSON(http.StatusOK, SyncStatusResponse{
LastComponentSync: lastComponentSync,
@@ -120,14 +97,14 @@ func (h *SyncHandler) GetStatus(c *gin.Context) {
LastPricelistAttemptAt: lastPricelistAttemptAt,
LastPricelistSyncStatus: lastPricelistSyncStatus,
LastPricelistSyncError: lastPricelistSyncError,
HasIncompleteServerSync: hasIncompleteServerSync,
KnownServerChangesMiss: knownServerChangesMissing,
HasIncompleteServerSync: hasFailedSync,
KnownServerChangesMiss: hasFailedSync,
IsOnline: isOnline,
ComponentsCount: componentsCount,
PricelistsCount: pricelistsCount,
ServerPricelists: serverPricelists,
ServerPricelists: 0,
NeedComponentSync: needComponentSync,
NeedPricelistSync: needPricelistSync,
NeedPricelistSync: lastPricelistSync == nil || hasFailedSync,
Readiness: readiness,
})
}
@@ -537,8 +514,8 @@ type SyncError struct {
// GetInfo returns sync information for modal
// GET /api/sync/info
func (h *SyncHandler) GetInfo(c *gin.Context) {
// Check online status by pinging MariaDB
isOnline := h.checkOnline()
connStatus := h.connMgr.GetStatus()
isOnline := connStatus.IsConnected && strings.TrimSpace(connStatus.LastError) == ""
// Get DB connection info
var dbHost, dbUser, dbName string
@@ -553,8 +530,9 @@ func (h *SyncHandler) GetInfo(c *gin.Context) {
lastPricelistAttemptAt := h.localDB.GetLastPricelistSyncAttemptAt()
lastPricelistSyncStatus := h.localDB.GetLastPricelistSyncStatus()
lastPricelistSyncError := h.localDB.GetLastPricelistSyncError()
needPricelistSync := false
hasIncompleteServerSync := false
hasFailedSync := strings.EqualFold(lastPricelistSyncStatus, "failed")
needPricelistSync := lastPricelistSync == nil || hasFailedSync
hasIncompleteServerSync := hasFailedSync
// Get local counts
configCount := h.localDB.CountConfigurations()
@@ -587,16 +565,7 @@ func (h *SyncHandler) GetInfo(c *gin.Context) {
syncErrors = syncErrors[:10]
}
readiness := h.getReadinessCached(10 * time.Second)
if isOnline {
if status, err := h.syncService.GetStatus(); err == nil {
lastPricelistAttemptAt = status.LastAttemptAt
lastPricelistSyncStatus = status.LastSyncStatus
lastPricelistSyncError = status.LastSyncError
needPricelistSync = status.NeedsSync
hasIncompleteServerSync = status.IncompleteServerSync
}
}
readiness := h.getReadinessLocal()
c.JSON(http.StatusOK, SyncInfoResponse{
DBHost: dbHost,
@@ -671,19 +640,12 @@ func (h *SyncHandler) SyncStatusPartial(c *gin.Context) {
// Get pending count
pendingCount := h.localDB.GetPendingCount()
readiness := h.getReadinessCached(10 * time.Second)
readiness := h.getReadinessLocal()
isBlocked := readiness != nil && readiness.Blocked
lastPricelistSyncStatus := h.localDB.GetLastPricelistSyncStatus()
lastPricelistSyncError := h.localDB.GetLastPricelistSyncError()
hasIncompleteServerSync := false
if !isOffline {
if status, err := h.syncService.GetStatus(); err == nil {
lastPricelistSyncStatus = status.LastSyncStatus
lastPricelistSyncError = status.LastSyncError
hasIncompleteServerSync = status.IncompleteServerSync
}
}
hasFailedSync := strings.EqualFold(lastPricelistSyncStatus, "failed")
hasIncompleteServerSync := hasFailedSync
slog.Debug("rendering sync status", "is_offline", isOffline, "pending_count", pendingCount, "sync_blocked", isBlocked)
@@ -721,20 +683,29 @@ func (h *SyncHandler) SyncStatusPartial(c *gin.Context) {
}
}
func (h *SyncHandler) getReadinessCached(maxAge time.Duration) *sync.SyncReadiness {
func (h *SyncHandler) getReadinessLocal() *sync.SyncReadiness {
h.readinessMu.Lock()
if h.readinessCached != nil && time.Since(h.readinessCachedAt) < maxAge {
if h.readinessCached != nil && time.Since(h.readinessCachedAt) < 10*time.Second {
cached := *h.readinessCached
h.readinessMu.Unlock()
return &cached
}
h.readinessMu.Unlock()
readiness, err := h.syncService.GetReadiness()
if err != nil && readiness == nil {
state, err := h.localDB.GetSyncGuardState()
if err != nil || state == nil {
return nil
}
readiness := &sync.SyncReadiness{
Status: state.Status,
Blocked: state.Status == sync.ReadinessBlocked,
ReasonCode: state.ReasonCode,
ReasonText: state.ReasonText,
RequiredMinAppVersion: state.RequiredMinAppVersion,
LastCheckedAt: state.LastCheckedAt,
}
h.readinessMu.Lock()
h.readinessCached = readiness
h.readinessCachedAt = time.Now()