feedback/internal/controller/feedback.go

148 lines
4.2 KiB
Go
Raw Normal View History

2023-04-20 02:03:21 +00:00
package controller
import (
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/backend/templategen_feedback/internal/client"
"penahub.gitlab.yandexcloud.net/backend/templategen_feedback/internal/models"
"penahub.gitlab.yandexcloud.net/backend/templategen_feedback/internal/repository"
)
// FeedbackController - контроллер формы обратной связи
type FeedbackController struct {
logger *zap.Logger
repository *repository.FeedbackRepository
telegram *client.Telegram
queue *FeedbackQueue
interrupter chan bool // Канал для прерывания работы сервиса контроллера
}
// NewFeedbackController - создать контроллер формы обратной связи
func NewFeedbackController(
logger *zap.Logger,
rep *repository.FeedbackRepository,
tg *client.Telegram) *FeedbackController {
return &FeedbackController{logger: logger, repository: rep, telegram: tg, queue: NewFeedbackQueue(), interrupter: make(chan bool, 1)}
}
// Register - регистрирует путь в fiber.
//
2023-05-05 18:08:17 +00:00
// Method: POST
2023-04-20 02:03:21 +00:00
// Path: /callme
// Name: callMe
func (r *FeedbackController) Register() (method, path, name string, handler fiber.Handler) {
2023-05-05 18:08:17 +00:00
return "POST", "/callme", "callMe", r.Handler
2023-04-20 02:03:21 +00:00
}
// Handler - Метод для отправки фидбэка. Складывает запрос в boltdb и отправляет на обработку в очередь
//
// Request: models.ReqFeedback
//
// Responses:
// Success
// Status: 200
// Body: nil
//
// Bad request - parsing error
// Status: 400
// Body: error
//
// Bad request - validation error
// Status: 400
// Body: { {field: string, tag: string, value: string}, ... }
//
// Internal server error - repository insert error
// Status: 500
// Body: error
//
// Service Unavailable - enqueue error
// Status: 503
// Body: nil
func (r *FeedbackController) Handler(c *fiber.Ctx) error {
var req models.ReqFeedback
err := c.BodyParser(&req)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
errValidate := validateStruct(&req)
if errValidate != nil {
return c.Status(fiber.StatusBadRequest).JSON(errValidate)
}
feedback := models.NewFeedback(c.Hostname(), req.Contact, req.WhoAmi)
// складываем в BoltDB на безопасное хранение
err = r.repository.Insert(feedback)
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
// отправляем в очередь сервиса
if !r.queue.Enqueue(feedback) {
return fiber.NewError(fiber.StatusServiceUnavailable)
}
return c.SendStatus(fiber.StatusOK)
}
// WarmUpService - прогревает сервис контроллера формы обратной связи перед запуском. Отправляет все фибдбэки из репозитория клиенту
func (r *FeedbackController) WarmUpService() error {
// достаем из BoltDB записи
tasks, err := r.repository.GetAll()
if err != nil {
return err
}
for _, task := range tasks {
_ = r.do(task)
}
return nil
}
// RunService - запуск сервиса контроллера формы обратной связи
func (r *FeedbackController) RunService() {
// запускаем цикл проверки очереди
for {
if r.queue.Len() > 0 {
task := r.queue.Dequeue()
if err := r.do(task); err != nil {
continue
}
}
select {
case <-r.interrupter:
break
default:
continue
}
}
}
// do - отправляет фидбэк в клиент и удаляет его из репозитория
func (r *FeedbackController) do(task *models.Feedback) error {
if task != nil {
if err := r.telegram.SendFeedback(task); err != nil {
r.logger.Error("CanNotSendFeedback", zap.Error(err))
return err
}
if err := r.repository.Delete(task.GetID()); err != nil {
r.logger.Error("CanNotDeleteFeedback", zap.Error(err))
return err
}
}
return nil
}
// StopService - остановить сервис контроллера формы обратной связи
func (r *FeedbackController) StopService() {
r.interrupter <- true
}