Fix recurring update issues (related to #671)
This commit addresses three recurring issues with the update system:
1. **Checksum mismatches (v4.27.0, v4.28.0):**
- Root cause: Release process uploads checksums.txt first, but if artifacts
are rebuilt after that upload, checksums become stale
- Fix: Update RELEASE_CHECKLIST.md to REQUIRE running validate-release.sh
before publishing (step 9, non-negotiable)
- The validation script exists and catches these errors, but wasn't being
enforced in the release process
2. **Duplicate error modals:**
- Root cause: UpdateProgressModal rendered in both App.tsx
(GlobalUpdateProgressWatcher) and UpdateBanner.tsx
- Fix: Remove UpdateProgressModal from UpdateBanner.tsx
- GlobalUpdateProgressWatcher automatically shows the modal when updates
start, so the banner's modal is redundant
3. **Rate limiting too strict:**
- Root cause: UpdateProgressModal polls /api/updates/status every 2 seconds
(30 req/min), but rate limit was 20/min
- Fix: Increase UpdateEndpoints rate limit from 20/min to 60/min
- Allows modal to poll without hitting rate limits during updates
These were all manual process errors and configuration issues, not code bugs.
The validation script enforcement prevents future checksum mismatches.
This commit is contained in:
parent
4c4fd3a99b
commit
e894bc7b1d
2 changed files with 4 additions and 23 deletions
|
|
@ -1,20 +1,14 @@
|
|||
import { Show, createSignal, createEffect, For, useContext } from 'solid-js';
|
||||
import { useNavigate } from '@solidjs/router';
|
||||
import { Show, createSignal, createEffect, For } from 'solid-js';
|
||||
import { updateStore } from '@/stores/updates';
|
||||
import { UpdatesAPI, type UpdatePlan } from '@/api/updates';
|
||||
import { UpdateConfirmationModal } from './UpdateConfirmationModal';
|
||||
import { UpdateProgressModal } from './UpdateProgressModal';
|
||||
import { WebSocketContext } from '@/App';
|
||||
import { copyToClipboard } from '@/utils/clipboard';
|
||||
import { logger } from '@/utils/logger';
|
||||
|
||||
export function UpdateBanner() {
|
||||
const navigate = useNavigate();
|
||||
const wsContext = useContext(WebSocketContext);
|
||||
const [isExpanded, setIsExpanded] = createSignal(false);
|
||||
const [updatePlan, setUpdatePlan] = createSignal<UpdatePlan | null>(null);
|
||||
const [showConfirmModal, setShowConfirmModal] = createSignal(false);
|
||||
const [showProgressModal, setShowProgressModal] = createSignal(false);
|
||||
const [isApplying, setIsApplying] = createSignal(false);
|
||||
const [copiedIndex, setCopiedIndex] = createSignal<number | null>(null);
|
||||
|
||||
|
|
@ -42,9 +36,8 @@ export function UpdateBanner() {
|
|||
setIsApplying(true);
|
||||
try {
|
||||
await UpdatesAPI.applyUpdate(info.downloadUrl);
|
||||
// Close confirmation and show progress
|
||||
// Close confirmation - GlobalUpdateProgressWatcher will auto-open the progress modal
|
||||
setShowConfirmModal(false);
|
||||
setShowProgressModal(true);
|
||||
} catch (error) {
|
||||
logger.error('Failed to start update', error);
|
||||
alert('Failed to start update. Please try again.');
|
||||
|
|
@ -295,18 +288,6 @@ export function UpdateBanner() {
|
|||
}}
|
||||
isApplying={isApplying()}
|
||||
/>
|
||||
|
||||
{/* Update Progress Modal */}
|
||||
<UpdateProgressModal
|
||||
isOpen={showProgressModal()}
|
||||
onClose={() => setShowProgressModal(false)}
|
||||
onViewHistory={() => {
|
||||
setShowProgressModal(false);
|
||||
navigate('/settings/updates');
|
||||
}}
|
||||
connected={wsContext?.connected}
|
||||
reconnecting={wsContext?.reconnecting}
|
||||
/>
|
||||
</Show>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ func InitializeRateLimiters() {
|
|||
// Recovery operations: extremely strict
|
||||
RecoveryEndpoints: NewRateLimiter(3, 10*time.Minute), // 3 attempts per 10 minutes
|
||||
|
||||
// Update operations: moderate limits
|
||||
UpdateEndpoints: NewRateLimiter(20, 1*time.Minute), // 20 checks per minute
|
||||
// Update operations: allow frequent polling during updates
|
||||
UpdateEndpoints: NewRateLimiter(60, 1*time.Minute), // 60 checks per minute (modal polls every 2s)
|
||||
|
||||
// WebSocket connections: per-connection limits
|
||||
WebSocketEndpoints: NewRateLimiter(30, 1*time.Minute), // 30 new connections per minute
|
||||
|
|
|
|||
Loading…
Reference in a new issue