// In-Memory Job-Status-Service für NPC-Erstellung // Für Produktion sollte man Redis oder eine Datenbank verwenden const jobs = new Map(); class NPCCreationJobService { createJob(userId, jobId) { jobs.set(jobId, { userId, status: 'pending', progress: 0, total: 0, current: 0, startTime: Date.now(), estimatedTimeRemaining: null, error: null, result: null }); return jobId; } getJob(jobId) { return jobs.get(jobId); } updateProgress(jobId, current, total) { const job = jobs.get(jobId); if (!job) return; job.current = current; job.total = total; job.progress = total > 0 ? Math.round((current / total) * 100) : 0; // Berechne verbleibende Zeit basierend auf bisheriger Geschwindigkeit if (current > 0 && job.progress < 100) { const elapsed = Date.now() - job.startTime; const avgTimePerItem = elapsed / current; const remaining = total - current; job.estimatedTimeRemaining = Math.round(remaining * avgTimePerItem); } } setStatus(jobId, status) { const job = jobs.get(jobId); if (!job) return; job.status = status; } setError(jobId, error) { const job = jobs.get(jobId); if (!job) return; job.status = 'error'; job.error = error; } setResult(jobId, result) { const job = jobs.get(jobId); if (!job) return; job.status = 'completed'; job.result = result; job.progress = 100; job.estimatedTimeRemaining = 0; } deleteJob(jobId) { jobs.delete(jobId); } // Cleanup alte Jobs (älter als 1 Stunde) cleanupOldJobs() { const oneHourAgo = Date.now() - (60 * 60 * 1000); for (const [jobId, job] of jobs.entries()) { if (job.startTime < oneHourAgo) { jobs.delete(jobId); } } } } // Cleanup alle 10 Minuten setInterval(() => { const service = new NPCCreationJobService(); service.cleanupOldJobs(); }, 10 * 60 * 1000); export default new NPCCreationJobService();