feat: optimize background tasks and fix warehouse pricelist workflow
Optimize task retention from 5 minutes to 30 seconds to reduce polling overhead since toast notifications are shown only once. Add conditional warehouse pricelist creation via checkbox. Fix category storage in warehouse pricelists to properly load from lot table. Replace SSE with task polling for all long operations. Add comprehensive logging for debugging while minimizing noise from polling endpoints. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package tasks
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -47,10 +48,13 @@ func (m *Manager) Submit(taskType TaskType, fn TaskFunc) string {
|
||||
m.tasks[taskID] = task
|
||||
m.mu.Unlock()
|
||||
|
||||
slog.Info("Task submitted", "task_id", taskID, "type", taskType)
|
||||
|
||||
// Start task in goroutine with panic recovery
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
slog.Error("Task panicked", "task_id", taskID, "type", taskType, "panic", r)
|
||||
m.updateTask(taskID, func(t *Task) {
|
||||
t.Status = TaskStatusError
|
||||
t.Error = fmt.Sprintf("Task panicked: %v", r)
|
||||
@@ -62,6 +66,7 @@ func (m *Manager) Submit(taskType TaskType, fn TaskFunc) string {
|
||||
|
||||
// Create progress callback
|
||||
progressCb := func(progress int, message string) {
|
||||
slog.Debug("Task progress", "task_id", taskID, "progress", progress, "message", message)
|
||||
m.updateTask(taskID, func(t *Task) {
|
||||
t.Progress = progress
|
||||
t.Message = message
|
||||
@@ -69,6 +74,7 @@ func (m *Manager) Submit(taskType TaskType, fn TaskFunc) string {
|
||||
}
|
||||
|
||||
// Execute task
|
||||
slog.Info("Task starting execution", "task_id", taskID, "type", taskType)
|
||||
ctx := context.Background()
|
||||
result, err := fn(ctx, progressCb)
|
||||
|
||||
@@ -79,9 +85,11 @@ func (m *Manager) Submit(taskType TaskType, fn TaskFunc) string {
|
||||
t.Progress = 100
|
||||
|
||||
if err != nil {
|
||||
slog.Error("Task failed", "task_id", taskID, "type", taskType, "error", err)
|
||||
t.Status = TaskStatusError
|
||||
t.Error = err.Error()
|
||||
} else {
|
||||
slog.Info("Task completed successfully", "task_id", taskID, "type", taskType, "result", result)
|
||||
t.Status = TaskStatusCompleted
|
||||
t.Result = result
|
||||
if t.Message == "Starting..." {
|
||||
@@ -94,16 +102,17 @@ func (m *Manager) Submit(taskType TaskType, fn TaskFunc) string {
|
||||
return taskID
|
||||
}
|
||||
|
||||
// List returns running tasks and completed tasks from the last 5 minutes
|
||||
// List returns running tasks and recently completed tasks (last 30 seconds)
|
||||
func (m *Manager) List() []*Task {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
|
||||
cutoff := time.Now().Add(-5 * time.Minute)
|
||||
// Keep completed tasks only for 30 seconds (enough to show toast notification)
|
||||
cutoff := time.Now().Add(-30 * time.Second)
|
||||
tasks := make([]*Task, 0, len(m.tasks))
|
||||
|
||||
for _, task := range m.tasks {
|
||||
// Include running tasks or recently completed tasks
|
||||
// Include running tasks or recently completed tasks (within 30 seconds)
|
||||
if task.Status == TaskStatusRunning ||
|
||||
(task.DoneAt != nil && task.DoneAt.After(cutoff)) {
|
||||
tasks = append(tasks, task)
|
||||
@@ -155,12 +164,12 @@ func (m *Manager) cleanupLoop() {
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup removes tasks completed more than 10 minutes ago
|
||||
// cleanup removes tasks completed more than 1 minute ago
|
||||
func (m *Manager) cleanup() {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
cutoff := time.Now().Add(-10 * time.Minute)
|
||||
cutoff := time.Now().Add(-1 * time.Minute)
|
||||
|
||||
for id, task := range m.tasks {
|
||||
if task.DoneAt != nil && task.DoneAt.Before(cutoff) {
|
||||
|
||||
Reference in New Issue
Block a user