Repository navigation
Expand file tree
/
Copy pathheartbeat_handler.go
More file actions
132 lines (115 loc) · 5.13 KB
/
Copy pathheartbeat_handler.go
File metadata and controls
132 lines (115 loc) · 5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package handlers
import (
"fmt"
"github.com/NdoleStudio/httpsms/pkg/requests"
"github.com/NdoleStudio/httpsms/pkg/services"
"github.com/NdoleStudio/httpsms/pkg/telemetry"
"github.com/NdoleStudio/httpsms/pkg/validators"
"github.com/davecgh/go-spew/spew"
"github.com/gofiber/fiber/v2"
"github.com/palantir/stacktrace"
)
// HeartbeatHandler handles heartbeat http requests.
type HeartbeatHandler struct {
handler
logger telemetry.Logger
tracer telemetry.Tracer
validator *validators.HeartbeatHandlerValidator
service *services.HeartbeatService
}
// NewHeartbeatHandler creates a new HeartbeatHandler
func NewHeartbeatHandler(
logger telemetry.Logger,
tracer telemetry.Tracer,
validator *validators.HeartbeatHandlerValidator,
service *services.HeartbeatService,
) (h *HeartbeatHandler) {
return &HeartbeatHandler{
logger: logger.WithService(fmt.Sprintf("%T", h)),
tracer: tracer,
validator: validator,
service: service,
}
}
// RegisterRoutes registers the routes for the MessageHandler
func (h *HeartbeatHandler) RegisterRoutes(router fiber.Router) {
router.Get("/heartbeats", h.Index)
router.Post("/heartbeats", h.Store)
}
// Index returns the heartbeats of a phone number
// @Summary Get heartbeats of an owner phone number
// @Description Get the last time a phone number requested for outstanding messages. It will be sorted by timestamp in descending order.
// @Security ApiKeyAuth
// @Tags Heartbeats
// @Accept json
// @Produce json
// @Param owner query string true "the owner's phone number" default(+18005550199)
// @Param skip query int false "number of heartbeats to skip" minimum(0)
// @Param query query string false "filter containing query"
// @Param limit query int false "number of heartbeats to return" minimum(1) maximum(20)
// @Success 200 {object} responses.HeartbeatsResponse
// @Failure 400 {object} responses.BadRequest
// @Failure 401 {object} responses.Unauthorized
// @Failure 422 {object} responses.UnprocessableEntity
// @Failure 500 {object} responses.InternalServerError
// @Router /heartbeats [get]
func (h *HeartbeatHandler) Index(c *fiber.Ctx) error {
ctx, span := h.tracer.StartFromFiberCtx(c)
defer span.End()
ctxLogger := h.tracer.CtxLogger(h.logger, span)
var request requests.HeartbeatIndex
if err := c.QueryParser(&request); err != nil {
msg := fmt.Sprintf("cannot marshall params [%s] into %T", c.OriginalURL(), request)
ctxLogger.Warn(stacktrace.Propagate(err, msg))
return h.responseBadRequest(c, err)
}
if errors := h.validator.ValidateIndex(ctx, request.Sanitize()); len(errors) != 0 {
msg := fmt.Sprintf("validation errors [%s], while fetching heartbeats [%+#v]", spew.Sdump(errors), request)
ctxLogger.Warn(stacktrace.NewError(msg))
return h.responseUnprocessableEntity(c, errors, "validation errors while fetching heartbeats")
}
heartbeats, err := h.service.Index(ctx, h.userIDFomContext(c), request.Owner, request.ToIndexParams())
if err != nil {
msg := fmt.Sprintf("cannot get messgaes with params [%+#v]", request)
ctxLogger.Error(stacktrace.Propagate(err, msg))
return h.responseInternalServerError(c)
}
return h.responseOK(c, fmt.Sprintf("fetched %d %s", len(*heartbeats), h.pluralize("heartbeat", len(*heartbeats))), heartbeats)
}
// Store the heartbeat of a phone number
// @Summary Register heartbeat of an owner phone number
// @Description Store the heartbeat to make notify that a phone number is still active
// @Security ApiKeyAuth
// @Tags Heartbeats
// @Accept json
// @Produce json
// @Param payload body requests.HeartbeatStore true "Payload of the heartbeat request"
// @Success 200 {object} responses.HeartbeatResponse
// @Failure 400 {object} responses.BadRequest
// @Failure 401 {object} responses.Unauthorized
// @Failure 422 {object} responses.UnprocessableEntity
// @Failure 500 {object} responses.InternalServerError
// @Router /heartbeats [post]
func (h *HeartbeatHandler) Store(c *fiber.Ctx) error {
ctx, span := h.tracer.StartFromFiberCtx(c)
defer span.End()
ctxLogger := h.tracer.CtxLogger(h.logger, span)
var request requests.HeartbeatStore
if err := c.BodyParser(&request); err != nil {
msg := fmt.Sprintf("cannot marshall params [%s] into %T", c.OriginalURL(), request)
ctxLogger.Warn(stacktrace.Propagate(err, msg))
return h.responseBadRequest(c, err)
}
if errors := h.validator.ValidateStore(ctx, request.Sanitize()); len(errors) != 0 {
msg := fmt.Sprintf("validation errors [%s], while storing heartbeat [%+#v]", spew.Sdump(errors), request)
ctxLogger.Warn(stacktrace.NewError(msg))
return h.responseUnprocessableEntity(c, errors, "validation errors while storing heartbeat")
}
heartbeat, err := h.service.Store(ctx, request.ToStoreParams(h.userFromContext(c), c.OriginalURL(), c.Get("X-Client-Version")))
if err != nil {
msg := fmt.Sprintf("cannot store heartbeat with params [%+#v]", request)
ctxLogger.Error(stacktrace.Propagate(err, msg))
return h.responseInternalServerError(c)
}
return h.responseCreated(c, "heartbeat created successfully", heartbeat)
}