tercul-backend/cmd/cli/commands/worker.go
Damir Mukimov d50722dad5
Some checks failed
Test / Integration Tests (push) Successful in 4s
Build / Build Binary (push) Failing after 2m9s
Docker Build / Build Docker Image (push) Failing after 2m32s
Test / Unit Tests (push) Failing after 3m12s
Lint / Go Lint (push) Failing after 1m0s
Refactor ID handling to use UUIDs across the application
- Updated database models and repositories to replace uint IDs with UUIDs.
- Modified test fixtures to generate and use UUIDs for authors, translations, users, and works.
- Adjusted mock implementations to align with the new UUID structure.
- Ensured all relevant functions and methods are updated to handle UUIDs correctly.
- Added necessary imports for UUID handling in various files.
2025-12-27 00:33:34 +01:00

145 lines
3.8 KiB
Go

package commands
import (
"os"
"os/signal"
"syscall"
"tercul/cmd/cli/internal/bootstrap"
dbsql "tercul/internal/data/sql"
"tercul/internal/jobs/linguistics"
"tercul/internal/jobs/sync"
"tercul/internal/platform/cache"
"tercul/internal/platform/config"
"tercul/internal/platform/db"
app_log "tercul/internal/platform/log"
"github.com/hibiken/asynq"
"github.com/spf13/cobra"
)
// NewWorkerCommand creates a new Cobra command for running background workers
func NewWorkerCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "worker",
Short: "Start the Tercul background worker",
Long: `Start the Tercul background worker to process async jobs including:
- Sync jobs (Weaviate indexing, etc.)
- Linguistic analysis jobs
- Trending calculation jobs`,
RunE: func(cmd *cobra.Command, args []string) error {
// Load configuration
cfg, err := config.LoadConfig()
if err != nil {
return err
}
// Initialize logger
app_log.Init("tercul-worker", cfg.Environment)
app_log.Info("Starting Tercul worker...")
// Initialize database connection
database, err := db.InitDB(cfg, nil) // No metrics needed for the worker
if err != nil {
app_log.Fatal(err, "Failed to initialize database")
}
defer func() {
if err := db.Close(database); err != nil {
app_log.Error(err, "Error closing database")
}
}()
// Initialize Weaviate client
weaviateClient, err := bootstrap.NewWeaviateClient(cfg)
if err != nil {
app_log.Fatal(err, "Failed to create weaviate client")
}
// Initialize Asynq client and server
redisConnection := asynq.RedisClientOpt{Addr: cfg.RedisAddr}
asynqClient := asynq.NewClient(redisConnection)
defer func() {
if err := asynqClient.Close(); err != nil {
app_log.Error(err, "Error closing asynq client")
}
}()
srv := asynq.NewServer(
redisConnection,
asynq.Config{
Concurrency: 10, // Example concurrency
Queues: map[string]int{
"critical": 6,
"default": 3,
"low": 1,
},
},
)
repos := dbsql.NewRepositories(database, cfg)
redisCache, cacheErr := cache.NewDefaultRedisCache(cfg)
if cacheErr != nil {
app_log.Warn("Redis cache initialization failed for linguistics: " + cacheErr.Error())
}
sentimentProvider, spErr := linguistics.NewGoVADERSentimentProvider()
if spErr != nil {
return spErr
}
workAnalyticsDeps := linguistics.WorkAnalyticsDeps{
StatsRepo: repos.Analytics,
LikeCounter: repos.Like,
CommentCounter: repos.Comment,
BookmarkCounter: repos.Bookmark,
TranslationCount: repos.Translation,
TranslationList: repos.Translation,
}
linguisticsFactory := linguistics.NewLinguisticsFactory(
cfg,
database,
redisCache,
2,
true,
sentimentProvider,
workAnalyticsDeps,
)
// Create SyncJob with all dependencies
syncJob := sync.NewSyncJob(database, asynqClient, cfg, weaviateClient)
linguisticJob := linguistics.NewLinguisticSyncJob(database, linguisticsFactory.GetAnalyzer(), asynqClient)
// Create a new ServeMux for routing jobs
mux := asynq.NewServeMux()
// Register all job handlers
sync.RegisterQueueHandlers(mux, syncJob)
linguistics.RegisterLinguisticHandlers(mux, linguisticJob)
// trending.RegisterTrendingHandlers(mux, analyticsService)
// Start the server in a goroutine
go func() {
if err := srv.Run(mux); err != nil {
app_log.Fatal(err, "Could not run asynq server")
}
}()
app_log.Info("Worker started successfully.")
// Wait for interrupt signal to gracefully shutdown the server
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
app_log.Info("Shutting down worker...")
srv.Shutdown()
app_log.Info("Worker shut down successfully.")
return nil
},
}
return cmd
}