feedback/internal/controller/feedback.go
2023-04-20 07:03:21 +05:00

148 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.
//
// Method: GET
// Path: /callme
// Name: callMe
func (r *FeedbackController) Register() (method, path, name string, handler fiber.Handler) {
return "GET", "/callme", "callMe", r.Handler
}
// 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
}