Skip to content

Commit dce720e

Browse files
committed
[lint] minor fixes
1 parent 671b0cc commit dce720e

File tree

9 files changed

+87
-69
lines changed

9 files changed

+87
-69
lines changed

internal/sms-gateway/handlers/messages/3rdparty.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package messages
22

33
import (
44
"errors"
5-
"fmt"
65
"strconv"
76
"time"
87

@@ -144,7 +143,14 @@ func (h *ThirdPartyController) post(user models.User, c *fiber.Ctx) error {
144143
return fiber.NewError(fiber.StatusConflict, err.Error())
145144
}
146145

147-
return fmt.Errorf("failed to enqueue message: %w", err)
146+
h.Logger.Error(
147+
"failed to enqueue message",
148+
zap.Error(err),
149+
zap.String("user_id", user.ID),
150+
zap.String("device_id", req.DeviceID),
151+
)
152+
153+
return fiber.NewError(fiber.StatusInternalServerError, "Failed to enqueue message. Please contact support")
148154
}
149155

150156
location, err := c.GetRouteURL(route3rdPartyGetMessage, fiber.Map{

internal/sms-gateway/modules/messages/models.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (m *Message) GetTextContent() (*TextMessageContent, error) {
7373

7474
content := new(TextMessageContent)
7575

76-
err := json.Unmarshal([]byte(m.Content), &content)
76+
err := json.Unmarshal([]byte(m.Content), content)
7777
if err != nil {
7878
return nil, fmt.Errorf("failed to unmarshal text content: %w", err)
7979
}

internal/sms-gateway/modules/messages/repository.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ func (r *Repository) UpdateState(message *Message) error {
155155
}
156156

157157
for _, v := range message.Recipients {
158-
if err := tx.Model(&MessageRecipient{}).
158+
if err := tx.Model((*MessageRecipient)(nil)).
159159
Where("message_id = ? AND phone_number = ?", message.ID, v.PhoneNumber).
160160
Select("state", "error").
161161
Updates(map[string]any{"state": v.State, "error": v.Error}).Error; err != nil {

internal/sms-gateway/modules/messages/service.go

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -173,37 +173,71 @@ func (s *Service) GetState(user models.User, id string) (*MessageStateOut, error
173173
return dto, nil
174174
}
175175

176-
func (s *Service) Enqueue(device models.Device, message MessageIn, opts EnqueueOptions) (MessageStateOut, error) {
177-
state := MessageStateOut{
176+
func (s *Service) Enqueue(device models.Device, message MessageIn, opts EnqueueOptions) (*MessageStateOut, error) {
177+
msg, err := s.prepareMessage(device, message, opts)
178+
if err != nil {
179+
return nil, err
180+
}
181+
182+
state := &MessageStateOut{
178183
DeviceID: device.ID,
179184
MessageStateIn: MessageStateIn{
180-
State: ProcessingStatePending,
181-
Recipients: make([]smsgateway.RecipientState, len(message.PhoneNumbers)),
185+
ID: msg.ExtID,
186+
State: ProcessingStatePending,
187+
Recipients: lo.Map(
188+
msg.Recipients,
189+
func(item MessageRecipient, _ int) smsgateway.RecipientState { return modelToRecipientState(item) },
190+
),
191+
States: map[string]time.Time{},
182192
},
193+
IsHashed: false,
194+
IsEncrypted: msg.IsEncrypted,
183195
}
184196

197+
if insErr := s.messages.Insert(msg); insErr != nil {
198+
return state, insErr
199+
}
200+
201+
if cacheErr := s.cache.Set(context.Background(), device.UserID, msg.ExtID, anys.AsPointer(modelToMessageState(*msg))); cacheErr != nil {
202+
s.logger.Warn("failed to cache message", zap.String("id", msg.ExtID), zap.Error(cacheErr))
203+
}
204+
s.metrics.IncTotal(string(msg.State))
205+
206+
go func(userID, deviceID string) {
207+
if ntfErr := s.eventsSvc.Notify(userID, &deviceID, events.NewMessageEnqueuedEvent()); ntfErr != nil {
208+
s.logger.Error(
209+
"failed to notify device",
210+
zap.Error(ntfErr),
211+
zap.String("user_id", userID),
212+
zap.String("device_id", deviceID),
213+
)
214+
}
215+
}(device.UserID, device.ID)
216+
217+
return state, nil
218+
}
219+
220+
func (s *Service) prepareMessage(device models.Device, message MessageIn, opts EnqueueOptions) (*Message, error) {
185221
var phone string
186222
var err error
187223
for i, v := range message.PhoneNumbers {
188224
if message.IsEncrypted || opts.SkipPhoneValidation {
189225
phone = v
190226
} else {
191227
if phone, err = cleanPhoneNumber(v); err != nil {
192-
return state, fmt.Errorf("failed to use phone in row %d: %w", i+1, err)
228+
return nil, fmt.Errorf("failed to use phone in row %d: %w", i+1, err)
193229
}
194230
}
195231

196232
message.PhoneNumbers[i] = phone
197-
198-
state.Recipients[i] = smsgateway.RecipientState{
199-
PhoneNumber: phone,
200-
State: smsgateway.ProcessingStatePending,
201-
}
202233
}
203234

204235
validUntil := message.ValidUntil
205236
if message.TTL != nil && *message.TTL > 0 {
206-
validUntil = anys.AsPointer(time.Now().Add(time.Duration(*message.TTL) * time.Second))
237+
//nolint:gosec // not a problem
238+
validUntil = anys.AsPointer(
239+
time.Now().Add(time.Duration(*message.TTL) * time.Second),
240+
)
207241
}
208242

209243
msg := Message{
@@ -221,43 +255,22 @@ func (s *Service) Enqueue(device models.Device, message MessageIn, opts EnqueueO
221255
}
222256

223257
if message.TextContent != nil {
224-
if err := msg.SetTextContent(*message.TextContent); err != nil {
225-
return state, fmt.Errorf("failed to set text content: %w", err)
258+
if setErr := msg.SetTextContent(*message.TextContent); setErr != nil {
259+
return nil, fmt.Errorf("failed to set text content: %w", setErr)
226260
}
227261
} else if message.DataContent != nil {
228-
if err := msg.SetDataContent(*message.DataContent); err != nil {
229-
return state, fmt.Errorf("failed to set data content: %w", err)
262+
if setErr := msg.SetDataContent(*message.DataContent); setErr != nil {
263+
return nil, fmt.Errorf("failed to set data content: %w", setErr)
230264
}
231265
} else {
232-
return state, ErrNoContent
266+
return nil, ErrNoContent
233267
}
234268

235269
if msg.ExtID == "" {
236270
msg.ExtID = s.idgen()
237271
}
238-
state.ID = msg.ExtID
239-
240-
if err := s.messages.Insert(&msg); err != nil {
241-
return state, err
242-
}
243-
244-
if err := s.cache.Set(context.Background(), device.UserID, msg.ExtID, anys.AsPointer(modelToMessageState(msg))); err != nil {
245-
s.logger.Warn("failed to cache message", zap.String("id", msg.ExtID), zap.Error(err))
246-
}
247-
s.metrics.IncTotal(string(msg.State))
248272

249-
go func(userID, deviceID string) {
250-
if err := s.eventsSvc.Notify(userID, &deviceID, events.NewMessageEnqueuedEvent()); err != nil {
251-
s.logger.Error(
252-
"failed to notify device",
253-
zap.Error(err),
254-
zap.String("user_id", userID),
255-
zap.String("device_id", deviceID),
256-
)
257-
}
258-
}(device.UserID, device.ID)
259-
260-
return state, nil
273+
return &msg, nil
261274
}
262275

263276
func (s *Service) ExportInbox(device models.Device, since, until time.Time) error {

internal/sms-gateway/online/metrics.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"github.com/prometheus/client_golang/prometheus/promauto"
66
)
77

8-
// Metric constants
8+
// Metric constants.
99
const (
1010
metricStatusSetTotal = "status_set_total"
1111
metricCacheOperations = "cache_operations_total"
@@ -24,7 +24,7 @@ const (
2424
statusError = "error"
2525
)
2626

27-
// metrics contains all Prometheus metrics for the online module
27+
// metrics contains all Prometheus metrics for the online module.
2828
type metrics struct {
2929
statusSetCounter *prometheus.CounterVec
3030
cacheOperations *prometheus.CounterVec
@@ -34,7 +34,7 @@ type metrics struct {
3434
batchSize prometheus.Gauge
3535
}
3636

37-
// newMetrics creates and initializes all online metrics
37+
// newMetrics creates and initializes all online metrics.
3838
func newMetrics() *metrics {
3939
return &metrics{
4040
statusSetCounter: promauto.NewCounterVec(prometheus.CounterOpts{
@@ -83,7 +83,7 @@ func newMetrics() *metrics {
8383
}
8484
}
8585

86-
// IncrementStatusSet increments the status set counter
86+
// IncrementStatusSet increments the status set counter.
8787
func (m *metrics) IncrementStatusSet(success bool) {
8888
status := statusSuccess
8989
if !success {
@@ -92,31 +92,31 @@ func (m *metrics) IncrementStatusSet(success bool) {
9292
m.statusSetCounter.WithLabelValues(status).Inc()
9393
}
9494

95-
// IncrementCacheOperation increments cache operation counter
95+
// IncrementCacheOperation increments cache operation counter.
9696
func (m *metrics) IncrementCacheOperation(operation, status string) {
9797
m.cacheOperations.WithLabelValues(operation, status).Inc()
9898
}
9999

100-
// ObserveCacheLatency observes cache operation latency
100+
// ObserveCacheLatency observes cache operation latency.
101101
func (m *metrics) ObserveCacheLatency(f func()) {
102102
timer := prometheus.NewTimer(m.cacheLatency)
103103
f()
104104
timer.ObserveDuration()
105105
}
106106

107-
// ObservePersistenceLatency observes persistence operation latency
107+
// ObservePersistenceLatency observes persistence operation latency.
108108
func (m *metrics) ObservePersistenceLatency(f func()) {
109109
timer := prometheus.NewTimer(m.persistenceLatency)
110110
f()
111111
timer.ObserveDuration()
112112
}
113113

114-
// IncrementPersistenceError increments persistence error counter
114+
// IncrementPersistenceError increments persistence error counter.
115115
func (m *metrics) IncrementPersistenceError() {
116116
m.persistenceErrors.Inc()
117117
}
118118

119-
// SetBatchSize sets the current batch size
119+
// SetBatchSize sets the current batch size.
120120
func (m *metrics) SetBatchSize(size int) {
121121
m.batchSize.Set(float64(size))
122122
}

internal/sms-gateway/online/service.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ func (s *service) persist(ctx context.Context) error {
9696
s.logger.Debug("Drained cache", zap.Int("count", len(items)))
9797

9898
timestamps := maps.MapValues(items, func(v []byte) time.Time {
99-
t, err := time.Parse(time.RFC3339, string(v))
100-
if err != nil {
101-
s.logger.Warn("failed to parse last seen", zap.String("last_seen", string(v)), zap.Error(err))
99+
t, parseErr := time.Parse(time.RFC3339, string(v))
100+
if parseErr != nil {
101+
s.logger.Warn("failed to parse last seen", zap.String("last_seen", string(v)), zap.Error(parseErr))
102102
return time.Now().UTC()
103103
}
104104

@@ -107,8 +107,8 @@ func (s *service) persist(ctx context.Context) error {
107107

108108
s.logger.Debug("Parsed last seen timestamps", zap.Int("count", len(timestamps)))
109109

110-
if err := s.devicesSvc.SetLastSeen(ctx, timestamps); err != nil {
111-
persistErr = fmt.Errorf("failed to set last seen: %w", err)
110+
if seenErr := s.devicesSvc.SetLastSeen(ctx, timestamps); seenErr != nil {
111+
persistErr = fmt.Errorf("failed to set last seen: %w", seenErr)
112112
s.metrics.IncrementPersistenceError()
113113
return
114114
}

internal/worker/locker/mysql.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func NewMySQLLocker(db *sql.DB, prefix string, timeout time.Duration) Locker {
2626
prefix: prefix,
2727
timeout: timeout,
2828

29+
mu: sync.Mutex{},
2930
conns: make(map[string]*sql.Conn),
3031
}
3132
}
@@ -41,9 +42,9 @@ func (m *mySQLLocker) AcquireLock(ctx context.Context, key string) error {
4142
}
4243

4344
var res sql.NullInt64
44-
if err := conn.QueryRowContext(ctx, "SELECT GET_LOCK(?, ?)", name, m.timeout.Seconds()).Scan(&res); err != nil {
45+
if lockErr := conn.QueryRowContext(ctx, "SELECT GET_LOCK(?, ?)", name, m.timeout.Seconds()).Scan(&res); lockErr != nil {
4546
_ = conn.Close()
46-
return fmt.Errorf("failed to get lock: %w", err)
47+
return fmt.Errorf("failed to get lock: %w", lockErr)
4748
}
4849
if !res.Valid || res.Int64 != 1 {
4950
_ = conn.Close()
@@ -70,7 +71,7 @@ func (m *mySQLLocker) ReleaseLock(ctx context.Context, key string) error {
7071
delete(m.conns, key)
7172
m.mu.Unlock()
7273
if conn == nil {
73-
return fmt.Errorf("no held connection for key %q", key)
74+
return fmt.Errorf("%w: no held connection for key %q", ErrLockNotAcquired, key)
7475
}
7576

7677
var result sql.NullInt64
@@ -81,7 +82,7 @@ func (m *mySQLLocker) ReleaseLock(ctx context.Context, key string) error {
8182
return fmt.Errorf("failed to release lock: %w", err)
8283
}
8384
if !result.Valid || result.Int64 != 1 {
84-
return fmt.Errorf("lock was not held or doesn't exist")
85+
return fmt.Errorf("%w: lock was not held or doesn't exist", ErrLockNotAcquired)
8586
}
8687

8788
return nil

pkg/cache/memory.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,9 @@ func (m *MemoryCache) Get(_ context.Context, key string, opts ...GetOption) ([]b
9494
m.mux.Lock()
9595
item, ok := m.items[key]
9696

97-
if !ok { //nolint:revive,gocritic //simplify code structure
98-
// item not found, nothing to do
99-
} else if o.delete {
97+
if ok && o.delete {
10098
delete(m.items, key)
101-
} else if !item.isExpired(time.Now()) {
99+
} else if ok && !item.isExpired(time.Now()) {
102100
switch {
103101
case o.validUntil != nil:
104102
item.validUntil = *o.validUntil

pkg/cache/memory_concurrency_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,12 @@ func TestMemoryCache_ConcurrentSetAndGetAndDelete(t *testing.T) {
157157
var wg sync.WaitGroup
158158

159159
// Launch goroutines that perform Set, Get, and Delete operations
160-
for i := 0; i < numGoroutines; i++ {
160+
for i := range numGoroutines {
161161
wg.Add(1)
162162
go func(goroutineID int) {
163163
defer wg.Done()
164164

165-
for j := 0; j < numOperations/numGoroutines; j++ {
165+
for j := range numOperations / numGoroutines {
166166
key := "key-" + strconv.Itoa(goroutineID) + "-" + strconv.Itoa(j)
167167
value := "value-" + strconv.Itoa(goroutineID) + "-" + strconv.Itoa(j)
168168

@@ -357,7 +357,7 @@ func TestMemoryCache_ConcurrentGetAndDelete(t *testing.T) {
357357
var wg sync.WaitGroup
358358

359359
// Pre-populate cache with items
360-
for i := 0; i < numGoroutines*attemptsPerGoroutine; i++ {
360+
for i := range numGoroutines * attemptsPerGoroutine {
361361
key := "item-" + strconv.Itoa(i)
362362
value := "value-" + strconv.Itoa(i)
363363

@@ -368,12 +368,12 @@ func TestMemoryCache_ConcurrentGetAndDelete(t *testing.T) {
368368
}
369369

370370
// Launch goroutines that perform GetAndDelete operations
371-
for i := 0; i < numGoroutines; i++ {
371+
for i := range numGoroutines {
372372
wg.Add(1)
373373
go func(goroutineID int) {
374374
defer wg.Done()
375375

376-
for j := 0; j < attemptsPerGoroutine; j++ {
376+
for j := range attemptsPerGoroutine {
377377
key := "item-" + strconv.Itoa(goroutineID*attemptsPerGoroutine+j)
378378

379379
_, err := c.GetAndDelete(ctx, key)

0 commit comments

Comments
 (0)