Update source code and remove runtime data from tracking
Add gitignore rules for browser session data, SQLite databases, media downloads, and build artifacts. Remove previously tracked runtime files from the repository. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
e90213d1ff
commit
dfa0580859
23 files changed
+5324
-347
No files matched your search
@@ -0,0 +1,119 @@
|
||||
import type { Logger } from '../utils/logger.js';
|
||||
import type { ChatService } from './chat.js';
|
||||
|
||||
export interface MediaSyncStatus {
|
||||
isSyncing: boolean;
|
||||
lastSyncAt: number | null;
|
||||
lastSyncDurationMs: number | null;
|
||||
lastSyncChats: number | null;
|
||||
lastError: string | null;
|
||||
nextSyncAt: number | null;
|
||||
}
|
||||
|
||||
export class MediaSyncService {
|
||||
private syncing = false;
|
||||
private lastSyncAt: number | null = null;
|
||||
private lastSyncDurationMs: number | null = null;
|
||||
private lastSyncChats: number | null = null;
|
||||
private lastError: string | null = null;
|
||||
private intervalHandle: NodeJS.Timeout | null = null;
|
||||
private readonly intervalMs: number;
|
||||
|
||||
constructor(
|
||||
private chatService: ChatService,
|
||||
private logger: Logger,
|
||||
intervalMs: number = 30 * 60 * 1000 // default 30 minutes
|
||||
) {
|
||||
this.intervalMs = intervalMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start periodic background syncing.
|
||||
*/
|
||||
start(): void {
|
||||
if (this.intervalHandle) return;
|
||||
|
||||
this.logger.info(`Media sync: starting background sync every ${Math.round(this.intervalMs / 60000)} min`);
|
||||
|
||||
// Run first sync after a short delay to let the app settle
|
||||
const initialDelay = setTimeout(() => this.runSync(), 15000);
|
||||
|
||||
this.intervalHandle = setInterval(() => this.runSync(), this.intervalMs);
|
||||
|
||||
// Ensure the initial timeout is cleaned up if stop() is called early
|
||||
const origStop = this.stop.bind(this);
|
||||
this.stop = () => {
|
||||
clearTimeout(initialDelay);
|
||||
origStop();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop periodic syncing.
|
||||
*/
|
||||
stop(): void {
|
||||
if (this.intervalHandle) {
|
||||
clearInterval(this.intervalHandle);
|
||||
this.intervalHandle = null;
|
||||
this.logger.info('Media sync: background sync stopped');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a sync manually (e.g. from the dashboard).
|
||||
* Returns immediately if a sync is already in progress.
|
||||
*/
|
||||
async triggerSync(full = false): Promise<boolean> {
|
||||
if (this.syncing) {
|
||||
this.logger.info('Media sync: sync already in progress, skipping trigger');
|
||||
return false;
|
||||
}
|
||||
await this.runSync(full);
|
||||
return true;
|
||||
}
|
||||
|
||||
getStatus(): MediaSyncStatus {
|
||||
return {
|
||||
isSyncing: this.syncing,
|
||||
lastSyncAt: this.lastSyncAt,
|
||||
lastSyncDurationMs: this.lastSyncDurationMs,
|
||||
lastSyncChats: this.lastSyncChats,
|
||||
lastError: this.lastError,
|
||||
nextSyncAt: this.intervalHandle && this.lastSyncAt
|
||||
? this.lastSyncAt + this.intervalMs
|
||||
: null,
|
||||
};
|
||||
}
|
||||
|
||||
private async runSync(full = false): Promise<void> {
|
||||
if (this.syncing) return;
|
||||
this.syncing = true;
|
||||
this.lastError = null;
|
||||
const start = Date.now();
|
||||
|
||||
try {
|
||||
if (full) {
|
||||
this.logger.info('Media sync: running full sync (all conversations)...');
|
||||
const chats = await this.chatService.fetchAllMessages();
|
||||
this.lastSyncChats = chats.length;
|
||||
} else {
|
||||
this.logger.info('Media sync: running incremental sync (top 10 chats)...');
|
||||
await this.chatService.refreshTopChats(10);
|
||||
this.lastSyncChats = 10;
|
||||
}
|
||||
|
||||
this.lastSyncAt = Date.now();
|
||||
this.lastSyncDurationMs = Date.now() - start;
|
||||
this.logger.info(
|
||||
`Media sync: completed in ${Math.round(this.lastSyncDurationMs / 1000)}s` +
|
||||
` (${this.lastSyncChats} chats)`
|
||||
);
|
||||
} catch (error) {
|
||||
this.lastError = error instanceof Error ? error.message : String(error);
|
||||
this.lastSyncDurationMs = Date.now() - start;
|
||||
this.logger.error('Media sync: failed:', error);
|
||||
} finally {
|
||||
this.syncing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user