fix ignore file

This commit is contained in:
Warunee Tamkoo 2026-03-07 21:14:50 +07:00
parent 76fc488d25
commit 91887ec63d

162
src/utils/sync-progress.ts Normal file
View file

@ -0,0 +1,162 @@
import * as fs from "fs";
import * as path from "path";
/**
* Interface for sync progress state
* Tracks the progress of batch sync operations
*/
export interface SyncProgressState {
lastSyncedIndex: number;
totalProfiles: number;
startTime: number;
lastUpdate: number;
failedProfiles: Array<{ index: number; profileId: string; error: string }>;
profileIds: string[]; // Track order of profile IDs for resume
}
/**
* SyncProgressManager
* Manages persistent storage of sync progress state
* Enables resuming from checkpoints after failures
*/
export class SyncProgressManager {
private static readonly FILE_PATH = ".sync-progress.json";
/**
* Save progress state to file
* @param state - Current progress state to save
*/
static save(state: SyncProgressState): void {
try {
const filePath = path.resolve(process.cwd(), this.FILE_PATH);
state.lastUpdate = Date.now();
fs.writeFileSync(filePath, JSON.stringify(state, null, 2), "utf-8");
} catch (error) {
console.error("[SyncProgressManager] Error saving progress:", error);
}
}
/**
* Load progress state from file
* @returns Progress state if exists, null otherwise
*/
static load(): SyncProgressState | null {
try {
const filePath = path.resolve(process.cwd(), this.FILE_PATH);
if (!fs.existsSync(filePath)) {
return null;
}
const data = fs.readFileSync(filePath, "utf-8");
const state = JSON.parse(data) as SyncProgressState;
// Validate required fields
if (
typeof state.lastSyncedIndex !== "number" ||
typeof state.totalProfiles !== "number" ||
!Array.isArray(state.failedProfiles) ||
!Array.isArray(state.profileIds)
) {
console.warn("[SyncProgressManager] Invalid progress file, starting fresh");
return null;
}
return state;
} catch (error) {
console.error("[SyncProgressManager] Error loading progress:", error);
return null;
}
}
/**
* Clear progress file
* Called on successful completion or when starting fresh
*/
static clear(): void {
try {
const filePath = path.resolve(process.cwd(), this.FILE_PATH);
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
console.log("[SyncProgressManager] Progress file cleared");
}
} catch (error) {
console.error("[SyncProgressManager] Error clearing progress:", error);
}
}
/**
* Get progress percentage
* @param state - Current progress state
* @returns Percentage complete (0-100)
*/
static getProgressPercent(state: SyncProgressState): number {
if (state.totalProfiles === 0) return 0;
return Math.round((state.lastSyncedIndex / state.totalProfiles) * 100);
}
/**
* Format elapsed time as readable string
* @param startTime - Start timestamp in milliseconds
* @returns Formatted time string (e.g., "2h 30m 15s")
*/
static formatElapsedTime(startTime: number): string {
const elapsed = Date.now() - startTime;
const seconds = Math.floor(elapsed / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const parts: string[] = [];
if (hours > 0) parts.push(`${hours}h`);
if (minutes % 60 > 0) parts.push(`${minutes % 60}m`);
if (seconds % 60 > 0 || parts.length === 0) parts.push(`${seconds % 60}s`);
return parts.join(" ");
}
/**
* Log current progress to console
* @param state - Current progress state
*/
static logProgress(state: SyncProgressState): void {
const percent = this.getProgressPercent(state);
const elapsed = this.formatElapsedTime(state.startTime);
const failed = state.failedProfiles.length;
console.log(
`[Sync Progress] ${percent}% (${state.lastSyncedIndex}/${state.totalProfiles}) | Elapsed: ${elapsed} | Failed: ${failed}`,
);
}
/**
* Add failed profile to state
* @param state - Progress state to update
* @param index - Profile index
* @param profileId - Profile ID that failed
* @param error - Error message
*/
static addFailedProfile(
state: SyncProgressState,
index: number,
profileId: string,
error: string,
): void {
state.failedProfiles.push({ index, profileId, error });
this.save(state);
}
/**
* Initialize new progress state
* @param profileIds - Array of profile IDs to sync
* @returns New progress state
*/
static initialize(profileIds: string[]): SyncProgressState {
return {
lastSyncedIndex: 0,
totalProfiles: profileIds.length,
startTime: Date.now(),
lastUpdate: Date.now(),
failedProfiles: [],
profileIds,
};
}
}