Fix BASE_URL config loading, add tasks/projects; robust .env path resolution
- Config: try ENV_FILE, .env, ../.env for loading; trim trailing slash from BaseURL - Log BASE_URL at server startup for verification - .env.example: document BASE_URL - Tasks, projects, tags, migrations and related API/handlers Made-with: Cursor
This commit is contained in:
91
internal/service/task_dependency.go
Normal file
91
internal/service/task_dependency.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/calendarapi/internal/models"
|
||||
"github.com/calendarapi/internal/repository"
|
||||
"github.com/calendarapi/internal/utils"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
type TaskDependencyService struct {
|
||||
queries *repository.Queries
|
||||
}
|
||||
|
||||
func NewTaskDependencyService(queries *repository.Queries) *TaskDependencyService {
|
||||
return &TaskDependencyService{queries: queries}
|
||||
}
|
||||
|
||||
func (s *TaskDependencyService) Add(ctx context.Context, userID uuid.UUID, taskID uuid.UUID, blocksTaskID uuid.UUID) error {
|
||||
if taskID == blocksTaskID {
|
||||
return models.NewValidationError("task cannot depend on itself")
|
||||
}
|
||||
|
||||
if _, err := s.queries.GetTaskByID(ctx, repository.GetTaskByIDParams{
|
||||
ID: utils.ToPgUUID(taskID),
|
||||
OwnerID: utils.ToPgUUID(userID),
|
||||
}); err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
return models.ErrInternal
|
||||
}
|
||||
|
||||
hasCircle, err := s.queries.CheckDirectCircularDependency(ctx, repository.CheckDirectCircularDependencyParams{
|
||||
BlocksTaskID: utils.ToPgUUID(taskID),
|
||||
TaskID: utils.ToPgUUID(blocksTaskID),
|
||||
})
|
||||
if err != nil {
|
||||
return models.ErrInternal
|
||||
}
|
||||
if hasCircle {
|
||||
return models.NewConflictError("circular dependency detected")
|
||||
}
|
||||
|
||||
return s.queries.AddTaskDependency(ctx, repository.AddTaskDependencyParams{
|
||||
TaskID: utils.ToPgUUID(taskID),
|
||||
BlocksTaskID: utils.ToPgUUID(blocksTaskID),
|
||||
})
|
||||
}
|
||||
|
||||
func (s *TaskDependencyService) Remove(ctx context.Context, userID uuid.UUID, taskID uuid.UUID, blocksTaskID uuid.UUID) error {
|
||||
if _, err := s.queries.GetTaskByID(ctx, repository.GetTaskByIDParams{
|
||||
ID: utils.ToPgUUID(taskID),
|
||||
OwnerID: utils.ToPgUUID(userID),
|
||||
}); err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
return models.ErrInternal
|
||||
}
|
||||
|
||||
return s.queries.RemoveTaskDependency(ctx, repository.RemoveTaskDependencyParams{
|
||||
TaskID: utils.ToPgUUID(taskID),
|
||||
BlocksTaskID: utils.ToPgUUID(blocksTaskID),
|
||||
})
|
||||
}
|
||||
|
||||
func (s *TaskDependencyService) ListBlockers(ctx context.Context, userID uuid.UUID, taskID uuid.UUID) ([]models.Task, error) {
|
||||
if _, err := s.queries.GetTaskByID(ctx, repository.GetTaskByIDParams{
|
||||
ID: utils.ToPgUUID(taskID),
|
||||
OwnerID: utils.ToPgUUID(userID),
|
||||
}); err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return nil, models.ErrNotFound
|
||||
}
|
||||
return nil, models.ErrInternal
|
||||
}
|
||||
|
||||
rows, err := s.queries.ListTaskBlockers(ctx, utils.ToPgUUID(taskID))
|
||||
if err != nil {
|
||||
return nil, models.ErrInternal
|
||||
}
|
||||
|
||||
tasks := make([]models.Task, 0, len(rows))
|
||||
for _, r := range rows {
|
||||
tasks = append(tasks, *taskFromDB(r))
|
||||
}
|
||||
return tasks, nil
|
||||
}
|
||||
Reference in New Issue
Block a user