mirror of
https://github.com/makayabou/asg-server.git
synced 2026-05-02 17:43:36 +02:00
Updated: db index and repository interface
This commit is contained in:
parent
38ff76cdaf
commit
29598c4f5f
15
db/migrations/20230925232629_ext_id_index.sql
Normal file
15
db/migrations/20230925232629_ext_id_index.sql
Normal file
@ -0,0 +1,15 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS `unq_messages_id_device` ON `messages`(`ext_id`, `device_id`);
|
||||
-- +goose StatementEnd
|
||||
-- +goose StatementBegin
|
||||
DROP INDEX IF EXISTS `unq_messages_device_id` ON `messages`;
|
||||
-- +goose StatementEnd
|
||||
--
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS `unq_messages_device_id` ON `messages`(`device_id`, `ext_id`);
|
||||
-- +goose StatementEnd
|
||||
-- +goose StatementBegin
|
||||
DROP INDEX IF EXISTS `unq_messages_id_device` ON `messages`;
|
||||
-- +goose StatementEnd
|
||||
@ -19,18 +19,18 @@ type thirdPartyHandler struct {
|
||||
messagesSvc *services.MessagesService
|
||||
}
|
||||
|
||||
// @Summary Поставить сообщение в очередь
|
||||
// @Description Ставит сообщение в очередь на отправку. Если идентификатор не указан, то он будет сгенерирован автоматически
|
||||
// @Security ApiAuth
|
||||
// @Tags Пользователь, Сообщения
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body smsgateway.Message true "Сообщение"
|
||||
// @Success 201 {object} smsgateway.MessageState "Сообщение поставлено в очередь"
|
||||
// @Failure 401 {object} smsgateway.ErrorResponse "Ошибка авторизации"
|
||||
// @Failure 400 {object} smsgateway.ErrorResponse "Некорректный запрос"
|
||||
// @Failure 500 {object} smsgateway.ErrorResponse "Внутренняя ошибка сервера"
|
||||
// @Router /3rdparty/v1/message [post]
|
||||
// @Summary Поставить сообщение в очередь
|
||||
// @Description Ставит сообщение в очередь на отправку. Если идентификатор не указан, то он будет сгенерирован автоматически
|
||||
// @Security ApiAuth
|
||||
// @Tags Пользователь, Сообщения
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body smsgateway.Message true "Сообщение"
|
||||
// @Success 201 {object} smsgateway.MessageState "Сообщение поставлено в очередь"
|
||||
// @Failure 401 {object} smsgateway.ErrorResponse "Ошибка авторизации"
|
||||
// @Failure 400 {object} smsgateway.ErrorResponse "Некорректный запрос"
|
||||
// @Failure 500 {object} smsgateway.ErrorResponse "Внутренняя ошибка сервера"
|
||||
// @Router /3rdparty/v1/message [post]
|
||||
func (h *thirdPartyHandler) postMessage(user models.User, c *fiber.Ctx) error {
|
||||
req := smsgateway.Message{}
|
||||
if err := h.BodyParserValidator(c, &req); err != nil {
|
||||
@ -54,6 +54,12 @@ func (h *thirdPartyHandler) postMessage(user models.User, c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusCreated).JSON(state)
|
||||
}
|
||||
|
||||
func (h *thirdPartyHandler) getMessage(user models.User, c *fiber.Ctx) error {
|
||||
// id := c.Params("id")
|
||||
|
||||
return fiber.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *thirdPartyHandler) authorize(handler func(models.User, *fiber.Ctx) error) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
username := c.Locals("username").(string)
|
||||
@ -77,6 +83,7 @@ func (h *thirdPartyHandler) register(router fiber.Router) {
|
||||
}))
|
||||
|
||||
router.Post("/message", h.authorize(h.postMessage))
|
||||
router.Get("/message/:id", h.authorize(h.getMessage))
|
||||
}
|
||||
|
||||
func newThirdPartyHandler(validator *validator.Validate, authSvc *services.AuthService, messagesSvc *services.MessagesService) *thirdPartyHandler {
|
||||
|
||||
@ -42,8 +42,8 @@ type Device struct {
|
||||
|
||||
type Message struct {
|
||||
ID uint64 `gorm:"primaryKey;type:BIGINT UNSIGNED;autoIncrement"`
|
||||
DeviceID string `gorm:"not null;type:char(21);uniqueIndex:unq_messages_device_id;index:idx_messages_device_state"`
|
||||
ExtID string `gorm:"not null;type:varchar(36);uniqueIndex:unq_messages_device_id"`
|
||||
DeviceID string `gorm:"not null;type:char(21);uniqueIndex:unq_messages_id_device,priority:2;index:idx_messages_device_state"`
|
||||
ExtID string `gorm:"not null;type:varchar(36);uniqueIndex:unq_messages_id_device,priority:1"`
|
||||
Message string `gorm:"not null;type:tinytext"`
|
||||
State MessageState `gorm:"not null;type:enum('Pending','Sent','Delivered','Failed');default:Pending;index:idx_messages_device_state"`
|
||||
|
||||
|
||||
@ -24,8 +24,24 @@ func (r *MessagesRepository) SelectPending(deviceID string) (messages []models.M
|
||||
return
|
||||
}
|
||||
|
||||
func (r *MessagesRepository) Get(deviceID, ID string) (message models.Message, err error) {
|
||||
err = r.db.Where("device_id = ? AND ext_id = ?", deviceID, ID).Take(&message).Error
|
||||
func (r *MessagesRepository) Get(ID string, filter MessagesSelectFilter, options ...MessagesSelectOptions) (message models.Message, err error) {
|
||||
query := r.db.Model(&message).
|
||||
Where("ext_id = ?", ID)
|
||||
|
||||
if filter.DeviceID != "" {
|
||||
query = query.Where("device_id = ?", filter.DeviceID)
|
||||
}
|
||||
|
||||
if len(options) > 0 {
|
||||
if options[0].WithRecipients {
|
||||
query = query.Preload("Recipients")
|
||||
}
|
||||
if options[0].WithDevice {
|
||||
query = query.Preload("Device")
|
||||
}
|
||||
}
|
||||
|
||||
err = query.Take(&message).Error
|
||||
|
||||
return
|
||||
}
|
||||
@ -55,3 +71,13 @@ func NewMessagesRepository(db *gorm.DB) *MessagesRepository {
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
type MessagesSelectFilter struct {
|
||||
DeviceID string
|
||||
}
|
||||
|
||||
type MessagesSelectOptions struct {
|
||||
WithRecipients bool
|
||||
WithDevice bool
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/models"
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/repositories"
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/pkg/slices"
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/pkg/smsgateway"
|
||||
"bitbucket.org/soft-c/gohelpers/pkg/filters"
|
||||
"github.com/jaevor/go-nanoid"
|
||||
@ -52,7 +53,7 @@ func (s *MessagesService) SelectPending(deviceID string) ([]smsgateway.Message,
|
||||
}
|
||||
|
||||
func (s *MessagesService) UpdateState(deviceID string, message smsgateway.MessageState) error {
|
||||
existing, err := s.Messages.Get(deviceID, message.ID)
|
||||
existing, err := s.Messages.Get(message.ID, repositories.MessagesSelectFilter{DeviceID: deviceID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -63,6 +64,15 @@ func (s *MessagesService) UpdateState(deviceID string, message smsgateway.Messag
|
||||
return s.Messages.UpdateState(&existing)
|
||||
}
|
||||
|
||||
func (s *MessagesService) GetState(deviceID, ID string) (smsgateway.MessageState, error) {
|
||||
message, err := s.Messages.Get(ID, repositories.MessagesSelectFilter{DeviceID: deviceID}, repositories.MessagesSelectOptions{WithRecipients: true})
|
||||
if err != nil {
|
||||
return smsgateway.MessageState{}, fmt.Errorf("can't get message for device %s and ID %s: %w", deviceID, ID, err)
|
||||
}
|
||||
|
||||
return modelToMessageState(message), nil
|
||||
}
|
||||
|
||||
func (s *MessagesService) Enqeue(device models.Device, message smsgateway.Message) (smsgateway.MessageState, error) {
|
||||
state := smsgateway.MessageState{
|
||||
ID: "",
|
||||
@ -148,3 +158,18 @@ func (s *MessagesService) recipientsStateToModel(input []smsgateway.RecipientSta
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
func modelToMessageState(input models.Message) smsgateway.MessageState {
|
||||
return smsgateway.MessageState{
|
||||
ID: input.ExtID,
|
||||
State: smsgateway.ProcessState(input.State),
|
||||
Recipients: slices.Map(input.Recipients, modelToRecipientState),
|
||||
}
|
||||
}
|
||||
|
||||
func modelToRecipientState(input models.MessageRecipient) smsgateway.RecipientState {
|
||||
return smsgateway.RecipientState{
|
||||
PhoneNumber: input.PhoneNumber,
|
||||
State: smsgateway.ProcessState(input.State),
|
||||
}
|
||||
}
|
||||
|
||||
9
pkg/slices/map.go
Normal file
9
pkg/slices/map.go
Normal file
@ -0,0 +1,9 @@
|
||||
package slices
|
||||
|
||||
func Map[T, U any](slice []T, f func(T) U) []U {
|
||||
result := make([]U, len(slice))
|
||||
for i, v := range slice {
|
||||
result[i] = f(v)
|
||||
}
|
||||
return result
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user