feat: improve error logging and enhance settings sync functionality
This commit is contained in:
@@ -47,7 +47,9 @@ export async function GET(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
return NextResponse.json({ settings });
|
return NextResponse.json({ settings });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('Settings load error', { error: error instanceof Error ? error.message : 'Unknown error' });
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||||
|
const code = (error as NodeJS.ErrnoException).code;
|
||||||
|
logger.error('Settings load error', { error: message, code });
|
||||||
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
|
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +76,9 @@ export async function POST(request: NextRequest) {
|
|||||||
await saveUserSettings(username, serverUrl, settings);
|
await saveUserSettings(username, serverUrl, settings);
|
||||||
return NextResponse.json({ ok: true });
|
return NextResponse.json({ ok: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('Settings save error', { error: error instanceof Error ? error.message : 'Unknown error' });
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||||
|
const code = (error as NodeJS.ErrnoException).code;
|
||||||
|
logger.error('Settings save error', { error: message, code });
|
||||||
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
|
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createHash, createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';
|
import { createHash, createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';
|
||||||
import { readFile, writeFile, unlink, mkdir } from 'node:fs/promises';
|
import { readFile, writeFile, unlink, mkdir, rename } from 'node:fs/promises';
|
||||||
import { existsSync } from 'node:fs';
|
import { existsSync } from 'node:fs';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { logger } from '@/lib/logger';
|
import { logger } from '@/lib/logger';
|
||||||
@@ -45,7 +45,10 @@ export async function saveUserSettings(username: string, serverUrl: string, sett
|
|||||||
const tag = cipher.getAuthTag();
|
const tag = cipher.getAuthTag();
|
||||||
|
|
||||||
const data = Buffer.concat([iv, tag, encrypted]);
|
const data = Buffer.concat([iv, tag, encrypted]);
|
||||||
await writeFile(getSettingsPath(username, serverUrl), data);
|
const targetPath = getSettingsPath(username, serverUrl);
|
||||||
|
const tmpPath = targetPath + '.tmp';
|
||||||
|
await writeFile(tmpPath, data);
|
||||||
|
await rename(tmpPath, targetPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadUserSettings(username: string, serverUrl: string): Promise<Record<string, unknown> | null> {
|
export async function loadUserSettings(username: string, serverUrl: string): Promise<Record<string, unknown> | null> {
|
||||||
|
|||||||
+23
-15
@@ -562,26 +562,34 @@ if (typeof window !== 'undefined') {
|
|||||||
applyAnimations(store.animationsEnabled);
|
applyAnimations(store.animationsEnabled);
|
||||||
|
|
||||||
// Shared sync function used by all store subscribers
|
// Shared sync function used by all store subscribers
|
||||||
|
const syncToServer = async (retries = 1): Promise<void> => {
|
||||||
|
const settings = JSON.parse(useSettingsStore.getState().exportSettings());
|
||||||
|
syncLog('Syncing settings to server...');
|
||||||
|
const res = await fetch('/api/settings', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ username: syncUsername, serverUrl: syncServerUrl, settings }),
|
||||||
|
});
|
||||||
|
if (res.status === 404) {
|
||||||
|
syncWarn('Settings sync endpoint returned 404, disabling sync');
|
||||||
|
syncEnabled = false;
|
||||||
|
} else if (res.status >= 500 && retries > 0) {
|
||||||
|
syncWarn('Settings sync got server error, retrying...');
|
||||||
|
await new Promise((r) => setTimeout(r, 2000));
|
||||||
|
return syncToServer(retries - 1);
|
||||||
|
} else if (!res.ok) {
|
||||||
|
syncError('Settings sync failed with status', res.status);
|
||||||
|
} else {
|
||||||
|
syncLog('Settings synced to server successfully');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const triggerSync = () => {
|
const triggerSync = () => {
|
||||||
if (!syncEnabled || !syncUsername || !syncServerUrl || isLoadingFromServer) return;
|
if (!syncEnabled || !syncUsername || !syncServerUrl || isLoadingFromServer) return;
|
||||||
if (syncTimeout) clearTimeout(syncTimeout);
|
if (syncTimeout) clearTimeout(syncTimeout);
|
||||||
syncTimeout = setTimeout(async () => {
|
syncTimeout = setTimeout(async () => {
|
||||||
try {
|
try {
|
||||||
const settings = JSON.parse(useSettingsStore.getState().exportSettings());
|
await syncToServer();
|
||||||
syncLog('Syncing settings to server...');
|
|
||||||
const res = await fetch('/api/settings', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ username: syncUsername, serverUrl: syncServerUrl, settings }),
|
|
||||||
});
|
|
||||||
if (res.status === 404) {
|
|
||||||
syncWarn('Settings sync endpoint returned 404, disabling sync');
|
|
||||||
syncEnabled = false;
|
|
||||||
} else if (!res.ok) {
|
|
||||||
syncError('Settings sync failed with status', res.status);
|
|
||||||
} else {
|
|
||||||
syncLog('Settings synced to server successfully');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
syncError('Settings sync error:', error);
|
syncError('Settings sync error:', error);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user