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
5 changes: 4 additions & 1 deletion cmd/psqlqueue/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,24 @@ func main() {
messageRepository := repository.NewMessage(pool)
topicRepository := repository.NewTopic(pool)
subscriptionRepository := repository.NewSubscription(pool)
healthCheckRepository := repository.NewHealthCheck(pool)

// services
queueService := service.NewQueue(queueRepository)
messageService := service.NewMessage(messageRepository, queueRepository)
topicService := service.NewTopic(topicRepository, subscriptionRepository, queueRepository, messageRepository)
subscriptionService := service.NewSubscription(subscriptionRepository)
healthCheckService := service.NewHealthCheck(healthCheckRepository)

// http handlers
queueHandler := http.NewQueueHandler(queueService)
messageHandler := http.NewMessageHandler(messageService)
topicHandler := http.NewTopicHandler(topicService)
subscriptionHandler := http.NewSubscriptionHandler(subscriptionService)
healthCheckHandler := http.NewHealthCheckHandler(healthCheckService)

// run http server
http.RunServer(c.Context, cfg, http.SetupRouter(logger, queueHandler, messageHandler, topicHandler, subscriptionHandler))
http.RunServer(c.Context, cfg, http.SetupRouter(logger, queueHandler, messageHandler, topicHandler, subscriptionHandler, healthCheckHandler))

return nil
},
Expand Down
36 changes: 36 additions & 0 deletions docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,34 @@ const docTemplate = `{
"host": "{{.Host}}",
"basePath": "{{.BasePath}}",
"paths": {
"/healthz": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"health-check"
],
"summary": "Execute a health check",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/HealthCheckResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/queue/{queue_id}/messages": {
"post": {
"consumes": [
Expand Down Expand Up @@ -987,6 +1015,14 @@ const docTemplate = `{
"subscriptionNotFound"
]
},
"HealthCheckResponse": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
}
},
"MessageListResponse": {
"type": "object",
"properties": {
Expand Down
36 changes: 36 additions & 0 deletions docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,34 @@
"contact": {}
},
"paths": {
"/healthz": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"health-check"
],
"summary": "Execute a health check",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/HealthCheckResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/queue/{queue_id}/messages": {
"post": {
"consumes": [
Expand Down Expand Up @@ -976,6 +1004,14 @@
"subscriptionNotFound"
]
},
"HealthCheckResponse": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
}
},
"MessageListResponse": {
"type": "object",
"properties": {
Expand Down
23 changes: 23 additions & 0 deletions docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ definitions:
- topicNotFound
- subscriptionAlreadyExists
- subscriptionNotFound
HealthCheckResponse:
properties:
success:
type: boolean
type: object
MessageListResponse:
properties:
data:
Expand Down Expand Up @@ -240,6 +245,24 @@ definitions:
info:
contact: {}
paths:
/healthz:
get:
consumes:
- application/json
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/HealthCheckResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ErrorResponse'
summary: Execute a health check
tags:
- health-check
/queue/{queue_id}/messages:
post:
consumes:
Expand Down
18 changes: 18 additions & 0 deletions domain/health_check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package domain

import "context"

// HealthCheck entity.
type HealthCheck struct {
Success bool `json:"success"`
}

// HealthCheckRepository is the repository interface for the HealthCheck entity.
type HealthCheckRepository interface {
Check(ctx context.Context) (*HealthCheck, error)
}

// HealthCheckService is the service interface for the HealthCheck entity.
type HealthCheckService interface {
Check(ctx context.Context) (*HealthCheck, error)
}
44 changes: 44 additions & 0 deletions http/health_check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package http

import (
"net/http"

"github.com/gin-gonic/gin"

"github.com/allisson/psqlqueue/domain"
)

// nolint:unused
type healthCheckResponse struct {
Success bool `json:"success"`
} //@name HealthCheckResponse

// HealthCheckHandler exposes a REST API for domain.HealthCheckService.
type HealthCheckHandler struct {
healthCheckService domain.HealthCheckService
}

// Execute a health check.
//
// @Summary Execute a health check
// @Tags health-check
// @Accept json
// @Produce json
// @Success 200 {object} healthCheckResponse
// @Failure 500 {object} errorResponse
// @Router /healthz [get]
func (h *HealthCheckHandler) Check(c *gin.Context) {
healthCheck, err := h.healthCheckService.Check(c.Request.Context())
if err != nil {
er := parseServiceError("healthCheckService", "Check", err)
c.JSON(er.StatusCode, &er)
return
}

c.JSON(http.StatusOK, &healthCheck)
}

// NewHealthCheckHandler returns a new HealthCheckHandler.
func NewHealthCheckHandler(healthCheckService domain.HealthCheckService) *HealthCheckHandler {
return &HealthCheckHandler{healthCheckService: healthCheckService}
}
27 changes: 27 additions & 0 deletions http/health_check_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package http

import (
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"

"github.com/allisson/psqlqueue/domain"
)

func TestHealthCheckHandler(t *testing.T) {
t.Run("Check", func(t *testing.T) {
expectedPayload := `{"success":true}`
tc := makeTestContext(t)
reqRec := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/v1/healthz", nil)

tc.healthCheckService.On("Check", mock.Anything).Return(&domain.HealthCheck{Success: true}, nil)
tc.router.ServeHTTP(reqRec, req)

assert.Equal(t, http.StatusOK, reqRec.Code)
assert.Equal(t, expectedPayload, reqRec.Body.String())
})
}
8 changes: 7 additions & 1 deletion http/queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type testContext struct {
topicHandler *TopicHandler
subscriptionService *mocks.SubscriptionService
subscriptionHandler *SubscriptionHandler
healthCheckService *mocks.HealthCheckService
healthCheckHandler *HealthCheckHandler
router *gin.Engine
}

Expand All @@ -37,7 +39,9 @@ func makeTestContext(t *testing.T) *testContext {
topicHandler := NewTopicHandler(topicService)
subscriptionService := mocks.NewSubscriptionService(t)
subscriptionHandler := NewSubscriptionHandler(subscriptionService)
router := SetupRouter(logger, queueHandler, messageHandler, topicHandler, subscriptionHandler)
healthCheckService := mocks.NewHealthCheckService(t)
healthCheckHandler := NewHealthCheckHandler(healthCheckService)
router := SetupRouter(logger, queueHandler, messageHandler, topicHandler, subscriptionHandler, healthCheckHandler)
return &testContext{
queueService: queueService,
queueHandler: queueHandler,
Expand All @@ -47,6 +51,8 @@ func makeTestContext(t *testing.T) *testContext {
topicHandler: topicHandler,
subscriptionService: subscriptionService,
subscriptionHandler: subscriptionHandler,
healthCheckService: healthCheckService,
healthCheckHandler: healthCheckHandler,
router: router,
}
}
Expand Down
5 changes: 4 additions & 1 deletion http/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"github.com/allisson/psqlqueue/domain"
)

func SetupRouter(logger *slog.Logger, queueHandler *QueueHandler, messageHandler *MessageHandler, topicHandler *TopicHandler, subscriptionHandler *SubscriptionHandler) *gin.Engine {
func SetupRouter(logger *slog.Logger, queueHandler *QueueHandler, messageHandler *MessageHandler, topicHandler *TopicHandler, subscriptionHandler *SubscriptionHandler, healthCheckHandler *HealthCheckHandler) *gin.Engine {
// router setup
gin.SetMode(gin.ReleaseMode)
router := gin.New()
Expand Down Expand Up @@ -64,6 +64,9 @@ func SetupRouter(logger *slog.Logger, queueHandler *QueueHandler, messageHandler
v1.GET("/subscriptions", subscriptionHandler.List)
v1.DELETE("/subscriptions/:subscription_id", subscriptionHandler.Delete)

// health check handler
v1.GET("/healthz", healthCheckHandler.Check)

return router
}

Expand Down
59 changes: 59 additions & 0 deletions mocks/HealthCheckRepository.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading