148 lines
4.2 KiB
Go
148 lines
4.2 KiB
Go
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
|
||
}
|