Skip to content

Commit

Permalink
⚡️ Added /criteria/init/v1 endpoint to initialize / enqueue the PENDI…
Browse files Browse the repository at this point in the history
…NG or IN PROGRESS criteria
  • Loading branch information
lhbelfanti committed Sep 20, 2024
1 parent 2e3d82f commit e90a715
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 4 deletions.
3 changes: 3 additions & 0 deletions Dockerfile_migrations → Dockerfile_db
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ ENV TZ=America/Argentina/Buenos_Aires
# Make HTTP request to /migrations/run/v1 endpoint
CMD ["sh", "-c", "curl -X POST http://ahbcc:${API_PORT}/migrations/run/v1"]

# Make HTTP request to /criteria/init/v1 endpoint
CMD ["sh", "-c", "curl -X POST http://ahbcc:${API_PORT}/criteria/init/v1"]

3 changes: 3 additions & 0 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,16 @@ func main() {
scrapperEnqueueCriteria := scrapper.MakeEnqueueCriteria(httpClient, os.Getenv("ENQUEUE_CRITERIA_API_URL"))
enqueueCriteria := criteria.MakeEnqueue(selectCriteriaByID, selectLastDayExecutedByCriteriaID, selectExecutionsByStatuses, scrapperEnqueueCriteria)

initCriteria := criteria.MakeInit(selectExecutionsByStatuses, enqueueCriteria)

/* --- Router --- */
log.Info(ctx, "Initializing router...")
router := http.NewServeMux()
router.HandleFunc("GET /ping/v1", ping.HandlerV1())
router.HandleFunc("POST /migrations/run/v1", migrations.RunHandlerV1(runMigrations))
router.HandleFunc("POST /tweets/v1", tweets.InsertHandlerV1(insertTweets))
router.HandleFunc("POST /criteria/{criteria_id}/enqueue/v1", criteria.EnqueueHandlerV1(enqueueCriteria))
router.HandleFunc("POST /criteria/init/v1", criteria.InitHandlerV1(initCriteria))
log.Info(ctx, "Router initialized!")

/* --- Server --- */
Expand Down
1 change: 1 addition & 0 deletions cmd/api/search/criteria/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const (
InvalidQueryParameterFormat string = "Invalid query parameter format"
FailedToEnqueueCriteria string = "Failed to execute enqueue criteria"
ExecutionWithSameCriteriaIDAlreadyEnqueued string = "An execution with the same criteria id is already enqueued"
FailedToExecuteInitCriteria string = "Failed to execute init criteria"
)

var (
Expand Down
20 changes: 19 additions & 1 deletion cmd/api/search/criteria/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"ahbcc/internal/log"
)

// EnqueueHandlerV1 HTTP Handler of the endpoint /criteria/enqueue/v1
// EnqueueHandlerV1 HTTP Handler of the endpoint /criteria/{criteria_id}/enqueue/v1
func EnqueueHandlerV1(enqueueCriteria Enqueue) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
Expand Down Expand Up @@ -47,3 +47,21 @@ func EnqueueHandlerV1(enqueueCriteria Enqueue) http.HandlerFunc {
_, _ = w.Write([]byte("Criteria successfully sent to enqueue"))
}
}

// InitHandlerV1 HTTP Handler of the endpoint /criteria/init/v1
func InitHandlerV1(init Init) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

err := init(ctx)
if err != nil {
log.Error(ctx, err.Error())
http.Error(w, FailedToExecuteInitCriteria, http.StatusInternalServerError)
return
}

log.Info(ctx, "Criteria successfully initialized and enqueued")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("Criteria successfully initialized and enqueued"))
}
}
32 changes: 32 additions & 0 deletions cmd/api/search/criteria/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,35 @@ func TestEnqueueHandlerV1_failsWhenEnqueueCriteriaThrowsError(t *testing.T) {
assert.Equal(t, want, got)
}
}

func TestInitHandlerV1_success(t *testing.T) {
mockInit := criteria.MockInit(nil)

mockResponseWriter := httptest.NewRecorder()
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/criteria/init", http.NoBody)

handlerV1 := criteria.InitHandlerV1(mockInit)

handlerV1(mockResponseWriter, mockRequest)

want := http.StatusOK
got := mockResponseWriter.Result().StatusCode

assert.Equal(t, want, got)
}

func TestInitHandlerV1_failsWhenInitThrowsError(t *testing.T) {
mockInit := criteria.MockInit(errors.New("failed while executing init criteria"))

mockResponseWriter := httptest.NewRecorder()
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/criteria/init", http.NoBody)

handlerV1 := criteria.InitHandlerV1(mockInit)

handlerV1(mockResponseWriter, mockRequest)

want := http.StatusInternalServerError
got := mockResponseWriter.Result().StatusCode

assert.Equal(t, want, got)
}
31 changes: 31 additions & 0 deletions cmd/api/search/criteria/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package criteria

import (
"context"

"ahbcc/internal/log"
)

// Init retrieves all the criteria in a 'PENDING' or 'IN PROGRESS' state and executes an enqueue of each one
type Init func(ctx context.Context) error

// MakeInit creates a new Init
func MakeInit(selectExecutionsByStatuses SelectExecutionsByStatuses, enqueue Enqueue) Init {
return func(ctx context.Context) error {
executionsDAO, err := selectExecutionsByStatuses(ctx, []string{PendingStatus, InProgressStatus})
if err != nil {
log.Error(ctx, err.Error())
return FailedToExecuteSelectExecutionsByStatuses
}

for _, execution := range executionsDAO {
err = enqueue(ctx, execution.SearchCriteriaID, true)
if err != nil {
log.Error(ctx, err.Error())
return FailedToExecuteEnqueueCriteria
}
}

return nil
}
}
48 changes: 48 additions & 0 deletions cmd/api/search/criteria/init_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package criteria_test

import (
"context"
"errors"
"testing"

"github.com/stretchr/testify/assert"

"ahbcc/cmd/api/search/criteria"
)

func TestInit_success(t *testing.T) {
mockExecutionsDAO := criteria.MockExecutionsDAO()
mockSelectExecutionsByStatuses := criteria.MockSelectExecutionsByStatuses(mockExecutionsDAO, nil)
mockEnqueue := criteria.MockEnqueue(nil)

init := criteria.MakeInit(mockSelectExecutionsByStatuses, mockEnqueue)

got := init(context.Background())

assert.Nil(t, got)
}

func TestInit_failsWhenSelectExecutionsByStatusesThrowsError(t *testing.T) {
mockSelectExecutionsByStatuses := criteria.MockSelectExecutionsByStatuses(nil, errors.New("failed while executing select executions by statuses"))
mockEnqueue := criteria.MockEnqueue(nil)

init := criteria.MakeInit(mockSelectExecutionsByStatuses, mockEnqueue)

want := criteria.FailedToExecuteSelectExecutionsByStatuses
got := init(context.Background())

assert.Equal(t, want, got)
}

func TestInit_failsWhenEnqueueThrowsError(t *testing.T) {
mockExecutionsDAO := criteria.MockExecutionsDAO()
mockSelectExecutionsByStatuses := criteria.MockSelectExecutionsByStatuses(mockExecutionsDAO, nil)
mockEnqueue := criteria.MockEnqueue(errors.New("failed while executing enqueue"))

init := criteria.MakeInit(mockSelectExecutionsByStatuses, mockEnqueue)

want := criteria.FailedToExecuteEnqueueCriteria
got := init(context.Background())

assert.Equal(t, want, got)
}
7 changes: 7 additions & 0 deletions cmd/api/search/criteria/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ func MockEnqueue(err error) Enqueue {
}
}

// MockInit mocks Init function
func MockInit(err error) Init {
return func(ctx context.Context) error {
return err
}
}

// MockCriteriaDAO mocks a criteria.DAO
func MockCriteriaDAO() DAO {
return DAO{
Expand Down
6 changes: 3 additions & 3 deletions compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ services:
timeout: 10s
retries: 5

migrations:
db_initializer:
image: alpine:latest
build:
context: .
dockerfile: Dockerfile_migrations
container_name: migrations
dockerfile: Dockerfile_db
container_name: db_initializer
environment:
API_PORT: ${APP_INTERNAL_PORT:-4001}
env_file:
Expand Down

0 comments on commit e90a715

Please sign in to comment.