feat: implement background task system with notifications
- Added background task manager with goroutine execution and panic recovery - Replaced SSE streaming with background task execution for: * Price recalculation (RecalculateAll) * Stock import (ImportStockLog) * Pricelist creation (CreateWithProgress) - Implemented unified polling for task status and DB connection in frontend - Added task indicator in top bar showing running tasks count - Added toast notifications for task completion/error - Tasks automatically cleaned up after 10 minutes - Tasks show progress (0-100%) with descriptive messages - Updated handler constructors to receive task manager - Added API endpoints for task status (/api/tasks, /api/tasks/:id) Fixes issue with SSE disconnection on slow connections during long-running operations
This commit is contained in:
@@ -30,6 +30,7 @@ import (
|
||||
"git.mchus.pro/mchus/priceforge/internal/services/alerts"
|
||||
"git.mchus.pro/mchus/priceforge/internal/services/pricelist"
|
||||
"git.mchus.pro/mchus/priceforge/internal/services/pricing"
|
||||
"git.mchus.pro/mchus/priceforge/internal/tasks"
|
||||
"github.com/gin-gonic/gin"
|
||||
mysqlDriver "github.com/go-sql-driver/mysql"
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -338,6 +339,9 @@ func setupRouter(cfg *config.Config, configPath string, connMgr *db.ConnectionMa
|
||||
pricelistService := pricelist.NewService(mariaDB, pricelistRepo, componentRepo, pricingService)
|
||||
stockImportService := services.NewStockImportService(mariaDB, pricelistService)
|
||||
|
||||
// Create task manager
|
||||
taskManager := tasks.NewManager()
|
||||
|
||||
templatesPath := filepath.Join("web", "templates")
|
||||
componentHandler := handlers.NewComponentHandler(componentService)
|
||||
pricingHandler := handlers.NewPricingHandler(
|
||||
@@ -345,12 +349,15 @@ func setupRouter(cfg *config.Config, configPath string, connMgr *db.ConnectionMa
|
||||
pricingService,
|
||||
alertService,
|
||||
componentRepo,
|
||||
componentService,
|
||||
priceRepo,
|
||||
statsRepo,
|
||||
stockImportService,
|
||||
dbUser,
|
||||
taskManager,
|
||||
)
|
||||
pricelistHandler := handlers.NewPricelistHandler(pricelistService, dbUser)
|
||||
pricelistHandler := handlers.NewPricelistHandler(pricelistService, dbUser, taskManager)
|
||||
taskHandler := tasks.NewHandler(taskManager)
|
||||
webHandler, err := handlers.NewWebHandler(templatesPath, componentService)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -550,6 +557,9 @@ func setupRouter(cfg *config.Config, configPath string, connMgr *db.ConnectionMa
|
||||
c.JSON(http.StatusOK, gin.H{"message": "pong"})
|
||||
})
|
||||
|
||||
api.GET("/tasks", taskHandler.List)
|
||||
api.GET("/tasks/:id", taskHandler.Get)
|
||||
|
||||
components := api.Group("/components")
|
||||
{
|
||||
components.GET("", componentHandler.List)
|
||||
@@ -583,6 +593,7 @@ func setupRouter(cfg *config.Config, configPath string, connMgr *db.ConnectionMa
|
||||
pricingAdmin.GET("/lots", pricingHandler.ListLots)
|
||||
pricingAdmin.GET("/lots-table", pricingHandler.ListLotsTable)
|
||||
pricingAdmin.POST("/lots", pricingHandler.CreateLot)
|
||||
pricingAdmin.POST("/lots/sync-metadata", pricingHandler.SyncLotsMetadata)
|
||||
pricingAdmin.POST("/stock/import", pricingHandler.ImportStockLog)
|
||||
pricingAdmin.GET("/stock/mappings", pricingHandler.ListStockMappings)
|
||||
pricingAdmin.POST("/stock/mappings", pricingHandler.UpsertStockMapping)
|
||||
|
||||
Reference in New Issue
Block a user