Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ ifeq ($(OS),Windows_NT)
endif

init:
go mod download \
&& go install github.com/pressly/goose/v3/cmd/goose@latest
go mod download

init-dev: init
go install github.com/cosmtrek/air@latest \
&& go install github.com/swaggo/swag/cmd/swag@latest
&& go install github.com/swaggo/swag/cmd/swag@latest \
&& go install github.com/pressly/goose/v3/cmd/goose@latest

air:
air
Expand Down
5 changes: 3 additions & 2 deletions api/local.http
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ Content-Type: application/json
Authorization: Basic {{localCredentials}}

{
"message": "Test",
"message": "{{$localDatetime iso8601}}",
"ttl": 600,
"phoneNumbers": [
"{{phone}}"
],
"simNumber": 1
"simNumber": 1,
"withDeliveryReport": true
}

###
Expand Down
3 changes: 2 additions & 1 deletion api/requests.http
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ Authorization: Basic {{credentials}}
"phoneNumbers": [
"{{phone}}"
],
"simNumber": 3
"simNumber": 1,
"withDeliveryReport": true
}

###
Expand Down
5 changes: 5 additions & 0 deletions api/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,11 @@
"type": "integer",
"minimum": 5,
"example": 86400
},
"withDeliveryReport": {
"description": "Запрашивать отчет о доставке",
"type": "boolean",
"example": true
}
}
},
Expand Down
4 changes: 4 additions & 0 deletions api/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ definitions:
example: 86400
minimum: 5
type: integer
withDeliveryReport:
description: Запрашивать отчет о доставке
example: true
type: boolean
required:
- message
- phoneNumbers
Expand Down
6 changes: 1 addition & 5 deletions internal/infra/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package logger

import (
"context"
"errors"
"os"
"syscall"

"go.uber.org/fx"
"go.uber.org/zap"
Expand All @@ -25,9 +23,7 @@ func New(lc fx.Lifecycle) (*zap.Logger, error) {

lc.Append(fx.Hook{
OnStop: func(ctx context.Context) error {
if err := l.Sync(); !errors.Is(err, syscall.ENOTTY) {
return err
}
_ = l.Sync()
return nil
},
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-- +goose Up
-- +goose StatementBegin
ALTER TABLE `messages`
ADD `with_delivery_report` tinyint(1) unsigned DEFAULT 1 NOT NULL;
-- +goose StatementEnd
---
-- +goose Down
-- +goose StatementBegin
ALTER TABLE `messages` DROP `with_delivery_report`;
-- +goose StatementEnd
15 changes: 8 additions & 7 deletions internal/sms-gateway/models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ 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_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','Processed','Delivered','Failed');default:Pending;index:idx_messages_device_state"`
ValidUntil *time.Time `gorm:"type:datetime"`
SimNumber *uint8 `gorm:"type:tinyint(1) unsigned"`
ID uint64 `gorm:"primaryKey;type:BIGINT UNSIGNED;autoIncrement"`
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','Processed','Delivered','Failed');default:Pending;index:idx_messages_device_state"`
ValidUntil *time.Time `gorm:"type:datetime"`
SimNumber *uint8 `gorm:"type:tinyint(1) unsigned"`
WithDeliveryReport bool `gorm:"not null;type:tinyint(1) unsigned"`

Device Device `gorm:"foreignKey:DeviceID;constraint:OnDelete:CASCADE"`
Recipients []MessageRecipient `gorm:"foreignKey:MessageID;constraint:OnDelete:CASCADE"`
Expand Down
24 changes: 13 additions & 11 deletions internal/sms-gateway/services/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,12 @@ func (s *MessagesService) SelectPending(deviceID string) ([]smsgateway.Message,
}

result[i] = smsgateway.Message{
ID: v.ExtID,
Message: v.Message,
TTL: ttl,
PhoneNumbers: s.recipientsToDomain(v.Recipients),
SimNumber: v.SimNumber,
ID: v.ExtID,
Message: v.Message,
TTL: ttl,
PhoneNumbers: s.recipientsToDomain(v.Recipients),
SimNumber: v.SimNumber,
WithDeliveryReport: types.AsPointer[bool](v.WithDeliveryReport),
}
}

Expand Down Expand Up @@ -129,12 +130,13 @@ func (s *MessagesService) Enqeue(device models.Device, message smsgateway.Messag
}

msg := models.Message{
DeviceID: device.ID,
ExtID: message.ID,
Message: message.Message,
ValidUntil: validUntil,
SimNumber: message.SimNumber,
Recipients: s.recipientsToModel(message.PhoneNumbers),
DeviceID: device.ID,
ExtID: message.ID,
Message: message.Message,
ValidUntil: validUntil,
SimNumber: message.SimNumber,
WithDeliveryReport: types.OrDefault[bool](message.WithDeliveryReport, true),
Recipients: s.recipientsToModel(message.PhoneNumbers),
}
if msg.ExtID == "" {
msg.ExtID = s.idgen()
Expand Down
28 changes: 16 additions & 12 deletions internal/sms-gateway/services/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ type PushService struct {
CredentialsJSON string

client *messaging.Client

once sync.Once
mux sync.Mutex
}

type PushServiceConfig struct {
Expand All @@ -29,20 +28,25 @@ func NewPushService(config PushServiceConfig) *PushService {

// init
func (s *PushService) init(ctx context.Context) (err error) {
s.once.Do(func() {
opt := option.WithCredentialsJSON([]byte(s.CredentialsJSON))
s.mux.Lock()
defer s.mux.Unlock()

var app *firebase.App
app, err = firebase.NewApp(ctx, nil, opt)
if s.client != nil {
return
}

if err != nil {
return
}
opt := option.WithCredentialsJSON([]byte(s.CredentialsJSON))

s.client, err = app.Messaging(ctx)
})
var app *firebase.App
app, err = firebase.NewApp(ctx, nil, opt)

return err
if err != nil {
return
}

s.client, err = app.Messaging(ctx)

return
}

// send
Expand Down
11 changes: 6 additions & 5 deletions pkg/smsgateway/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ const (

// Сообщение
type Message struct {
ID string `json:"id,omitempty" validate:"omitempty,max=36" example:"PyDmBQZZXYmyxMwED8Fzy"` // Идентификатор
Message string `json:"message" validate:"required,max=256" example:"Hello World!"` // Текст сообщения
TTL *uint64 `json:"ttl,omitempty" validate:"omitempty,min=5" example:"86400"` // Время жизни сообщения в секундах
SimNumber *uint8 `json:"simNumber,omitempty" validate:"omitempty,max=3" example:"1"` // Номер сим-карты
PhoneNumbers []string `json:"phoneNumbers" validate:"required,min=1,max=100,dive,required,min=10" example:"79990001234"` // Получатели
ID string `json:"id,omitempty" validate:"omitempty,max=36" example:"PyDmBQZZXYmyxMwED8Fzy"` // Идентификатор
Message string `json:"message" validate:"required,max=256" example:"Hello World!"` // Текст сообщения
TTL *uint64 `json:"ttl,omitempty" validate:"omitempty,min=5" example:"86400"` // Время жизни сообщения в секундах
SimNumber *uint8 `json:"simNumber,omitempty" validate:"omitempty,max=3" example:"1"` // Номер сим-карты
WithDeliveryReport *bool `json:"withDeliveryReport,omitempty" example:"true"` // Запрашивать отчет о доставке
PhoneNumbers []string `json:"phoneNumbers" validate:"required,min=1,max=100,dive,required,min=10" example:"79990001234"` // Получатели
}

// Состояние сообщения
Expand Down
7 changes: 7 additions & 0 deletions pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@ package types
func AsPointer[T any](v T) *T {
return &v
}

func OrDefault[T any](v *T, def T) T {
if v == nil {
return def
}
return *v
}