Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/nadmax/nexq/internal/api"
"github.com/nadmax/nexq/internal/middleware"
"github.com/nadmax/nexq/internal/queue"
"github.com/nadmax/nexq/internal/repository"
"github.com/nadmax/nexq/internal/repository/postgres"
)

func main() {
Expand All @@ -26,7 +26,7 @@ func main() {
log.Fatal("POSTGRES_DSN is required")
}

repo, err := repository.NewPostgresTaskRepository(postgresDSN)
repo, err := postgres.NewPostgresTaskRepository(postgresDSN)
if err != nil {
log.Fatal(err)
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/worker/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"time"

"github.com/nadmax/nexq/internal/queue"
"github.com/nadmax/nexq/internal/repository"
"github.com/nadmax/nexq/internal/repository/postgres"
"github.com/nadmax/nexq/internal/task"
"github.com/nadmax/nexq/internal/worker"
"github.com/nadmax/nexq/internal/worker/handlers"
Expand All @@ -28,7 +28,7 @@ func main() {
log.Fatal("POSTGRES_DSN is required")
}

repo, err := repository.NewPostgresTaskRepository(postgresDSN)
repo, err := postgres.NewPostgresTaskRepository(postgresDSN)
if err != nil {
log.Fatal(err)
}
Expand Down
2 changes: 2 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ignore:
- "**/mocks/**"
28 changes: 14 additions & 14 deletions internal/api/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import (

"github.com/alicebob/miniredis/v2"
"github.com/nadmax/nexq/internal/queue"
"github.com/nadmax/nexq/internal/repository"
"github.com/nadmax/nexq/internal/repository/mocks"
"github.com/nadmax/nexq/internal/repository/models"
"github.com/nadmax/nexq/internal/task"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand All @@ -29,11 +30,11 @@ func setupTestAPI(t *testing.T) (*API, *queue.Queue, *miniredis.Miniredis) {
return api, q, mr
}

func setupTestAPIWithMockRepo(t *testing.T) (*API, *queue.Queue, *repository.MockPostgresRepository, *miniredis.Miniredis) {
func setupTestAPIWithMockRepo(t *testing.T) (*API, *queue.Queue, *mocks.MockPostgresRepository, *miniredis.Miniredis) {
mr, err := miniredis.Run()
require.NoError(t, err)

mockRepo := repository.NewMockPostgresRepository()
mockRepo := mocks.NewMockPostgresRepository()
q, err := queue.NewQueue(mr.Addr(), mockRepo)
require.NoError(t, err)

Expand Down Expand Up @@ -639,7 +640,7 @@ func TestHistoryStatsWithMockRepo(t *testing.T) {
defer mr.Close()
defer func() { _ = q.Close() }()

mockRepo.TaskStats = []repository.TaskStats{
mockRepo.TaskStats = []models.TaskStats{
{
Type: "send_email",
Status: "completed",
Expand All @@ -658,7 +659,7 @@ func TestHistoryStatsWithMockRepo(t *testing.T) {

assert.Equal(t, http.StatusOK, w.Code)

var stats []repository.TaskStats
var stats []models.TaskStats
err := json.NewDecoder(w.Body).Decode(&stats)
require.NoError(t, err)
assert.Len(t, stats, 1)
Expand Down Expand Up @@ -686,7 +687,7 @@ func TestHandleRecentHistory_Success(t *testing.T) {

duration1 := 250
duration2 := 150
mockRepo.RecentTasks = []repository.RecentTask{
mockRepo.RecentTasks = []models.RecentTask{
{
TaskID: "task-1",
Type: "send_email",
Expand All @@ -710,7 +711,7 @@ func TestHandleRecentHistory_Success(t *testing.T) {

assert.Equal(t, http.StatusOK, w.Code)

var tasks []repository.RecentTask
var tasks []models.RecentTask
err := json.NewDecoder(w.Body).Decode(&tasks)
require.NoError(t, err)
assert.Len(t, tasks, 2)
Expand All @@ -722,23 +723,22 @@ func TestHandleRecentHistory_WithLimit(t *testing.T) {
defer mr.Close()
defer func() { _ = q.Close() }()

mockRepo.RecentTasks = []repository.RecentTask{}
mockRepo.RecentTasks = []models.RecentTask{}

w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/api/history/recent?limit=50", nil)

api.handleRecentHistory(w, r)

assert.Equal(t, http.StatusOK, w.Code)
// The limit is passed to the repository method, which uses it internally
}

func TestHandleRecentHistory_InvalidLimit(t *testing.T) {
api, q, mockRepo, mr := setupTestAPIWithMockRepo(t)
defer mr.Close()
defer func() { _ = q.Close() }()

mockRepo.RecentTasks = []repository.RecentTask{}
mockRepo.RecentTasks = []models.RecentTask{}

w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/api/history/recent?limit=invalid", nil)
Expand Down Expand Up @@ -805,7 +805,7 @@ func TestHandleTaskHistory_Success(t *testing.T) {
defer func() { _ = q.Close() }()

taskID := "task-123"
mockRepo.ExecutionLog = []repository.LogExecutionCall{
mockRepo.ExecutionLog = []mocks.LogExecutionCall{
{
TaskID: taskID,
AttemptNumber: 1,
Expand Down Expand Up @@ -910,7 +910,7 @@ func TestHandleTasksByType_Success(t *testing.T) {
taskType := "send_email"
duration1 := 200
duration2 := 300
mockRepo.RecentTasks = []repository.RecentTask{
mockRepo.RecentTasks = []models.RecentTask{
{
TaskID: "task-1",
Type: taskType,
Expand All @@ -934,7 +934,7 @@ func TestHandleTasksByType_Success(t *testing.T) {

assert.Equal(t, http.StatusOK, w.Code)

var tasks []repository.RecentTask
var tasks []models.RecentTask
err := json.NewDecoder(w.Body).Decode(&tasks)
require.NoError(t, err)
assert.Len(t, tasks, 2)
Expand All @@ -946,7 +946,7 @@ func TestHandleTasksByType_WithLimit(t *testing.T) {
defer mr.Close()
defer func() { _ = q.Close() }()

mockRepo.RecentTasks = []repository.RecentTask{}
mockRepo.RecentTasks = []models.RecentTask{}

w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/api/history/type/send_email?limit=25", nil)
Expand Down
24 changes: 12 additions & 12 deletions internal/dashboard/dashboard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (

"github.com/alicebob/miniredis/v2"
"github.com/nadmax/nexq/internal/queue"
"github.com/nadmax/nexq/internal/repository"
"github.com/nadmax/nexq/internal/repository/mocks"
"github.com/nadmax/nexq/internal/repository/models"
"github.com/nadmax/nexq/internal/task"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand All @@ -26,11 +27,11 @@ func setupTestDashboard(t *testing.T) (*Dashboard, *queue.Queue, *miniredis.Mini
return dash, q, mr
}

func setupTestDashboardWithMockRepo(t *testing.T) (*Dashboard, *queue.Queue, *repository.MockPostgresRepository, *miniredis.Miniredis) {
func setupTestDashboardWithMockRepo(t *testing.T) (*Dashboard, *queue.Queue, *mocks.MockPostgresRepository, *miniredis.Miniredis) {
mr, err := miniredis.Run()
require.NoError(t, err)

mockRepo := repository.NewMockPostgresRepository()
mockRepo := mocks.NewMockPostgresRepository()
q, err := queue.NewQueue(mr.Addr(), mockRepo)
require.NoError(t, err)

Expand Down Expand Up @@ -491,7 +492,7 @@ func TestGetStatsWithRepository(t *testing.T) {
defer mr.Close()
defer func() { _ = q.Close() }()

mockRepo.TaskStats = []repository.TaskStats{
mockRepo.TaskStats = []models.TaskStats{
{
Type: "send_email",
Status: "completed",
Expand Down Expand Up @@ -539,7 +540,7 @@ func TestGetRecentTasksWithRepository(t *testing.T) {
defer func() { _ = q.Close() }()

now := time.Now()
mockRepo.RecentTasks = []repository.RecentTask{
mockRepo.RecentTasks = []models.RecentTask{
{
TaskID: "task-1",
Type: "send_email",
Expand Down Expand Up @@ -612,7 +613,7 @@ func TestGetStatsWithCompletedTasks(t *testing.T) {
defer mr.Close()
defer func() { _ = q.Close() }()

mockRepo.TaskStats = []repository.TaskStats{
mockRepo.TaskStats = []models.TaskStats{
{
Type: "send_email",
Status: "completed",
Expand All @@ -639,7 +640,7 @@ func TestGetRecentTasksWithVariedStatuses(t *testing.T) {

now := time.Now()

mockRepo.RecentTasks = []repository.RecentTask{
mockRepo.RecentTasks = []models.RecentTask{
{
TaskID: "completed-task",
Type: "test_task",
Expand Down Expand Up @@ -685,8 +686,7 @@ func TestGetStatsPerformanceMetrics(t *testing.T) {
defer mr.Close()
defer func() { _ = q.Close() }()

// Setup performance data
mockRepo.TaskStats = []repository.TaskStats{
mockRepo.TaskStats = []models.TaskStats{
{
Type: "fast_task",
Status: "completed",
Expand Down Expand Up @@ -727,7 +727,7 @@ func TestGetRecentTasksOrdering(t *testing.T) {

now := time.Now()

mockRepo.RecentTasks = []repository.RecentTask{
mockRepo.RecentTasks = []models.RecentTask{
{
TaskID: "newest",
Type: "test",
Expand Down Expand Up @@ -761,7 +761,7 @@ func TestGetStatsWithRetryMetrics(t *testing.T) {
defer mr.Close()
defer func() { _ = q.Close() }()

mockRepo.TaskStats = []repository.TaskStats{
mockRepo.TaskStats = []models.TaskStats{
{
Type: "reliable_task",
Status: "completed",
Expand Down Expand Up @@ -793,7 +793,7 @@ func TestGetRecentTasksWithFailureReasons(t *testing.T) {

now := time.Now()

mockRepo.RecentTasks = []repository.RecentTask{
mockRepo.RecentTasks = []models.RecentTask{
{
TaskID: "failed-1",
Type: "test",
Expand Down
6 changes: 3 additions & 3 deletions internal/queue/queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"time"

"github.com/alicebob/miniredis/v2"
"github.com/nadmax/nexq/internal/repository"
"github.com/nadmax/nexq/internal/repository/mocks"
"github.com/nadmax/nexq/internal/task"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand All @@ -21,11 +21,11 @@ func setupTestQueue(t *testing.T) (*Queue, *miniredis.Miniredis) {
return q, mr
}

func setupTestQueueWithMockRepo(t *testing.T) (*Queue, *repository.MockPostgresRepository, *miniredis.Miniredis) {
func setupTestQueueWithMockRepo(t *testing.T) (*Queue, *mocks.MockPostgresRepository, *miniredis.Miniredis) {
mr, err := miniredis.Run()
require.NoError(t, err)

mockRepo := repository.NewMockPostgresRepository()
mockRepo := mocks.NewMockPostgresRepository()
q, err := NewQueue(mr.Addr(), mockRepo)
require.NoError(t, err)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package repository
// Package mocks provides mock implementations of repository interfaces for use in tests.
package mocks

import (
"context"
"fmt"
"sync"

"github.com/nadmax/nexq/internal/repository/models"
"github.com/nadmax/nexq/internal/task"
)

Expand All @@ -20,8 +22,8 @@ type MockPostgresRepository struct {
LogExecutionCalls []LogExecutionCall
Tasks map[string]*task.Task
ExecutionLog []LogExecutionCall
TaskStats []TaskStats
RecentTasks []RecentTask
TaskStats []models.TaskStats
RecentTasks []models.RecentTask
GetTaskError error
SaveTaskError error
CompleteTaskError error
Expand Down Expand Up @@ -74,8 +76,8 @@ func NewMockPostgresRepository() *MockPostgresRepository {
return &MockPostgresRepository{
Tasks: make(map[string]*task.Task),
ExecutionLog: make([]LogExecutionCall, 0),
TaskStats: make([]TaskStats, 0),
RecentTasks: make([]RecentTask, 0),
TaskStats: make([]models.TaskStats, 0),
RecentTasks: make([]models.RecentTask, 0),
}
}

Expand Down Expand Up @@ -233,7 +235,7 @@ func (m *MockPostgresRepository) LogExecution(ctx context.Context, taskID string
return nil
}

func (m *MockPostgresRepository) GetTaskStats(ctx context.Context, hours int) ([]TaskStats, error) {
func (m *MockPostgresRepository) GetTaskStats(ctx context.Context, hours int) ([]models.TaskStats, error) {
m.mu.Lock()
defer m.mu.Unlock()

Expand All @@ -244,7 +246,7 @@ func (m *MockPostgresRepository) GetTaskStats(ctx context.Context, hours int) ([
return m.TaskStats, nil
}

func (m *MockPostgresRepository) GetRecentTasks(ctx context.Context, limit int) ([]RecentTask, error) {
func (m *MockPostgresRepository) GetRecentTasks(ctx context.Context, limit int) ([]models.RecentTask, error) {
m.mu.Lock()
defer m.mu.Unlock()

Expand All @@ -259,15 +261,15 @@ func (m *MockPostgresRepository) GetRecentTasks(ctx context.Context, limit int)
return m.RecentTasks, nil
}

func (m *MockPostgresRepository) GetTasksByType(ctx context.Context, taskType string, limit int) ([]RecentTask, error) {
func (m *MockPostgresRepository) GetTasksByType(ctx context.Context, taskType string, limit int) ([]models.RecentTask, error) {
m.mu.Lock()
defer m.mu.Unlock()

if m.GetTasksByTypeError != nil {
return nil, m.GetTasksByTypeError
}

var filtered []RecentTask
var filtered []models.RecentTask
for _, task := range m.RecentTasks {
if task.Type == taskType {
filtered = append(filtered, task)
Expand Down
25 changes: 25 additions & 0 deletions internal/repository/models/task.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Package models contains data structures used by the task repository layer.
package models

import "time"

type TaskStats struct {
Type string `json:"type"`
Status string `json:"status"`
Count int `json:"count"`
AvgDurationMs float64 `json:"avg_duration_ms"`
MaxDurationMs int `json:"max_duration_ms"`
MinDurationMs int `json:"min_duration_ms"`
AvgRetries float64 `json:"avg_retries"`
}

type RecentTask struct {
TaskID string `json:"task_id"`
Type string `json:"type"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
DurationMs *int `json:"duration_ms,omitempty"`
RetryCount int `json:"retry_count"`
FailureReason string `json:"failure_reason,omitempty"`
}
Loading