2023-04-20 02:03:21 +00:00
|
|
|
|
package controller
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
|
|
|
"go.uber.org/zap"
|
2024-06-07 14:36:23 +00:00
|
|
|
|
"penahub.gitlab.yandexcloud.net/backend/penahub_common/log_mw"
|
2023-04-20 02:03:21 +00:00
|
|
|
|
"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"
|
2024-05-28 13:01:55 +00:00
|
|
|
|
"time"
|
2023-04-20 02:03:21 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 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 {
|
2024-06-07 14:36:23 +00:00
|
|
|
|
hloger := log_mw.ExtractLogger(c)
|
2023-04-20 02:03:21 +00:00
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-28 13:01:55 +00:00
|
|
|
|
hloger.Emit(models.InfoFeedbackRequested{
|
2024-06-07 14:36:23 +00:00
|
|
|
|
CtxRowData: req.Contact,
|
|
|
|
|
CtxID: req.WhoAmi,
|
2024-05-28 13:01:55 +00:00
|
|
|
|
})
|
|
|
|
|
|
2023-04-20 02:03:21 +00:00
|
|
|
|
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:
|
2023-07-14 10:23:36 +00:00
|
|
|
|
time.Sleep(time.Second)
|
2023-04-20 02:03:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
}
|