Skip to content

Commit 28b8794

Browse files
committed
Add api to fetch outstanding messages
1 parent c5831dd commit 28b8794

14 files changed

Lines changed: 280 additions & 41 deletions

api/go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.18
55
require (
66
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
77
github.com/cloudevents/sdk-go/v2 v2.10.0
8+
github.com/cockroachdb/cockroach-go/v2 v2.2.11
89
github.com/davecgh/go-spew v1.1.1
910
github.com/go-redis/redis/v8 v8.11.5
1011
github.com/gofiber/fiber/v2 v2.34.0
@@ -55,7 +56,7 @@ require (
5556
go.uber.org/atomic v1.6.0 // indirect
5657
go.uber.org/multierr v1.5.0 // indirect
5758
go.uber.org/zap v1.13.0 // indirect
58-
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
59+
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 // indirect
5960
golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect
6061
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 // indirect
6162
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect

api/go.sum

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ github.com/cloudevents/sdk-go/v2 v2.10.0 h1:sz0pbNBGh1iRspqLGe/2cXhDghZZpvNPHwKP
2020
github.com/cloudevents/sdk-go/v2 v2.10.0/go.mod h1:GpCBmUj7DIRiDhVvsK5d6WCbgTWs8DxAWTRtAwQmIXs=
2121
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
2222
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
23+
github.com/cockroachdb/cockroach-go/v2 v2.2.11 h1:gddwKS4W+zxfZdA0/dEMMjiruiQCCrG2iRbk0c1T13Y=
24+
github.com/cockroachdb/cockroach-go/v2 v2.2.11/go.mod h1:xZ2VHjUEb/cySv0scXBx7YsBnHtLHkR1+w/w73b5i3M=
2325
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
2426
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
2527
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
@@ -65,6 +67,8 @@ github.com/gofiber/fiber/v2 v2.34.0 h1:96BJMw6uaxQhJsHY54SFGOtGgp9pgombK5Hbi4JSE
6567
github.com/gofiber/fiber/v2 v2.34.0/go.mod h1:ozRQfS+D7EL1+hMH+gutku0kfx1wLX4hAxDCtDzpj4U=
6668
github.com/gofiber/swagger v0.0.1 h1:Qwt6uehJffeMG7zla3ampguOPtAW5K4xDAmpaL1qwXk=
6769
github.com/gofiber/swagger v0.0.1/go.mod h1:gal49FHSULvKAl9Ta+W7fRHdlTWhHPvArmsxKaIdLw4=
70+
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
71+
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
6872
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
6973
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
7074
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
@@ -93,6 +97,7 @@ github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8
9397
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
9498
github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
9599
github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
100+
github.com/jackc/pgconn v1.12.0/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono=
96101
github.com/jackc/pgconn v1.12.1 h1:rsDFzIpRk7xT4B8FufgpCCeyjdNpKyghZeSefViE5W8=
97102
github.com/jackc/pgconn v1.12.1/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono=
98103
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
@@ -129,6 +134,7 @@ github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQ
129134
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
130135
github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M=
131136
github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw=
137+
github.com/jackc/pgx/v4 v4.16.0/go.mod h1:N0A9sFdWzkw/Jy1lwoiB64F2+ugFZi987zRxcPez/wI=
132138
github.com/jackc/pgx/v4 v4.16.1 h1:JzTglcal01DrghUqt+PmzWsZx/Yh7SC/CTQmSBMTd0Y=
133139
github.com/jackc/pgx/v4 v4.16.1/go.mod h1:SIhx0D5hoADaiXZVyv+3gSm3LCIIINTVO0PficsvWGQ=
134140
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
@@ -140,6 +146,7 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
140146
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
141147
github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas=
142148
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
149+
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
143150
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
144151
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
145152
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -162,8 +169,9 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
162169
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
163170
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
164171
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
165-
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
166172
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
173+
github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
174+
github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
167175
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
168176
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
169177
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
@@ -174,6 +182,7 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope
174182
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
175183
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
176184
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
185+
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
177186
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
178187
github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0=
179188
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
@@ -210,8 +219,9 @@ github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+
210219
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
211220
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
212221
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
213-
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
214222
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
223+
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
224+
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
215225
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
216226
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
217227
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -276,8 +286,9 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y
276286
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
277287
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
278288
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
279-
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
280289
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
290+
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 h1:O8uGbHCqlTp2P6QJSLmCojM4mN6UemYv8K+dCnmHmu0=
291+
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
281292
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
282293
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
283294
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@@ -316,6 +327,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
316327
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
317328
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
318329
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
330+
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
319331
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
320332
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
321333
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@@ -372,6 +384,7 @@ gorm.io/datatypes v1.0.6/go.mod h1:Gh/Xd/iUWWybMEk8CzYCK/swqlni2r+ROeM1HGIM0ck=
372384
gorm.io/driver/mysql v1.3.2 h1:QJryWiqQ91EvZ0jZL48NOpdlPdMjdip1hQ8bTgo4H7I=
373385
gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U=
374386
gorm.io/driver/postgres v1.3.1/go.mod h1:WwvWOuR9unCLpGWCL6Y3JOeBWvbKi6JLhayiVclSZZU=
387+
gorm.io/driver/postgres v1.3.5/go.mod h1:EGCWefLFQSVFrHGy4J8EtiHCWX5Q8t0yz2Jt9aKkGzU=
375388
gorm.io/driver/postgres v1.3.7 h1:FKF6sIMDHDEvvMF/XJvbnCl0nu6KSKUaPXevJ4r+VYQ=
376389
gorm.io/driver/postgres v1.3.7/go.mod h1:f02ympjIcgtHEGFMZvdgTxODZ9snAHDb4hXfigBVuNI=
377390
gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk=

api/main.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package main
22

33
import (
4-
"log"
5-
64
_ "github.com/NdoleStudio/http-sms-manager/docs"
75
"github.com/NdoleStudio/http-sms-manager/pkg/di"
86
"github.com/gofiber/fiber/v2"
@@ -23,7 +21,7 @@ import (
2321
// @host api.httpsms.com
2422
// @BasePath /v1
2523
func main() {
26-
// di.LoadEnv()
24+
di.LoadEnv()
2725

2826
app := fiber.New()
2927

@@ -32,9 +30,10 @@ func main() {
3230
container := di.NewContainer("http-sms")
3331

3432
apiV1 := app.Group("v1")
35-
apiV1.Post("/messages/send", container.MessageHandler().Send)
33+
apiV1.Post("/messages/send", container.MessageHandler().PostSend)
34+
apiV1.Get("/messages/outstanding", container.MessageHandler().GetOutstanding)
3635

3736
app.Get("/*", swagger.HandlerDefault)
3837

39-
log.Println(app.Listen(":8000"))
38+
container.Logger().Info(app.Listen(":8000").Error())
4039
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
package events
22

3+
import (
4+
"github.com/google/uuid"
5+
)
6+
37
// EventTypeMessagePhoneSending is emitted when a message is picked up by the phone and is being sent
48
const EventTypeMessagePhoneSending = "message.phone.sending"
9+
10+
// MessagePhoneSendingPayload is the payload of the EventTypeMessageSent event
11+
type MessagePhoneSendingPayload struct {
12+
ID uuid.UUID `json:"id"`
13+
}

api/pkg/handlers/handler.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,10 @@ func (h *handler) responseOK(c *fiber.Ctx, message string, data interface{}) err
5656
"data": data,
5757
})
5858
}
59+
60+
func (h *handler) pluralize(value string, count int) string {
61+
if count == 1 {
62+
return value
63+
}
64+
return value + "s"
65+
}

api/pkg/handlers/message_handler.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,19 @@ func NewMessageHandler(
3636
}
3737
}
3838

39-
// Send a new entities.Message
39+
// PostSend a new entities.Message
4040
// @Summary Send a new SMS message
4141
// @Description Add a new SMS message to be sent by the android phone
4242
// @Tags Messages
4343
// @Accept json
4444
// @Produce json
45-
// @Param payload body requests.MessageSend true "Send message request payload"
45+
// @Param payload body requests.MessageSend true "PostSend message request payload"
4646
// @Success 200 {object} responses.MessageResponse
4747
// @Success 400 {object} responses.BadRequest
4848
// @Success 422 {object} responses.UnprocessableEntity
4949
// @Success 500 {object} responses.InternalServerError
5050
// @Router /messages/send [post]
51-
func (h *MessageHandler) Send(c *fiber.Ctx) error {
51+
func (h *MessageHandler) PostSend(c *fiber.Ctx) error {
5252
ctx, span := h.tracer.StartFromFiberCtx(c)
5353
defer span.End()
5454

@@ -76,3 +76,44 @@ func (h *MessageHandler) Send(c *fiber.Ctx) error {
7676

7777
return h.responseOK(c, "message added to queue", message)
7878
}
79+
80+
// GetOutstanding returns entities.Message which are still to be sent by the mobile phone
81+
// @Summary Get messages which are to be sent
82+
// @Description Get list of messages which are outstanding to be sent by the phone
83+
// @Tags Messages
84+
// @Accept json
85+
// @Produce json
86+
// @Param take query int false "number of outstanding messages to return" minimum(1) maximum(10)
87+
// @Success 200 {object} responses.MessagesResponse
88+
// @Success 400 {object} responses.BadRequest
89+
// @Success 422 {object} responses.UnprocessableEntity
90+
// @Success 500 {object} responses.InternalServerError
91+
// @Router /messages/outstanding [get]
92+
func (h *MessageHandler) GetOutstanding(c *fiber.Ctx) error {
93+
ctx, span := h.tracer.StartFromFiberCtx(c)
94+
defer span.End()
95+
96+
ctxLogger := h.tracer.CtxLogger(h.logger, span)
97+
98+
var request requests.MessageOutstanding
99+
if err := c.QueryParser(&request); err != nil {
100+
msg := fmt.Sprintf("cannot marshall params [%s] into %T", c.OriginalURL(), request)
101+
ctxLogger.Warn(stacktrace.Propagate(err, msg))
102+
return h.responseBadRequest(c, err)
103+
}
104+
105+
if errors := h.validator.ValidateMessageOutstanding(ctx, request.Sanitize()); len(errors) != 0 {
106+
msg := fmt.Sprintf("validation errors [%s], while fetching outstanding messages [%s]", spew.Sdump(errors), c.OriginalURL())
107+
ctxLogger.Warn(stacktrace.NewError(msg))
108+
return h.responseUnprocessableEntity(c, errors, "validation errors while fetching outstanding messages")
109+
}
110+
111+
messages, err := h.service.GetOutstanding(ctx, request.ToGetOutstandingParams(c.OriginalURL()))
112+
if err != nil {
113+
msg := fmt.Sprintf("cannot get messgaes with URL [%s]", c.OriginalURL())
114+
ctxLogger.Error(stacktrace.Propagate(err, msg))
115+
return h.responseInternalServerError(c)
116+
}
117+
118+
return h.responseOK(c, fmt.Sprintf("fetch %d %s", len(*messages), h.pluralize("message", len(*messages))), messages)
119+
}

api/pkg/repositories/gorm_message_repository.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import (
44
"context"
55
"fmt"
66

7+
"gorm.io/gorm/clause"
8+
79
"github.com/NdoleStudio/http-sms-manager/pkg/entities"
810
"github.com/NdoleStudio/http-sms-manager/pkg/telemetry"
11+
"github.com/cockroachdb/cockroach-go/v2/crdb/crdbgorm"
912
"github.com/google/uuid"
1013
"github.com/palantir/stacktrace"
1114
"gorm.io/gorm"
@@ -18,6 +21,35 @@ type gormMessageRepository struct {
1821
db *gorm.DB
1922
}
2023

24+
// GetOutstanding fetches messages that still to be sent to the phone
25+
func (repository *gormMessageRepository) GetOutstanding(ctx context.Context, take int) (*[]entities.Message, error) {
26+
ctx, span := repository.tracer.Start(ctx)
27+
defer span.End()
28+
29+
messages := new([]entities.Message)
30+
err := crdbgorm.ExecuteTx(ctx, repository.db, nil,
31+
func(tx *gorm.DB) error {
32+
return tx.Model(messages).
33+
Clauses(clause.Returning{}).
34+
Where(
35+
"id IN (?)",
36+
tx.Model(&entities.Message{}).
37+
Where("status = ?", entities.MessageStatusPending).
38+
Order("request_received_at ASC").
39+
Select("id").
40+
Limit(take),
41+
).
42+
Update("status", "sending").Error
43+
},
44+
)
45+
if err != nil {
46+
msg := fmt.Sprintf("cannot fetch [%d] outstanding messages", take)
47+
return nil, repository.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
48+
}
49+
50+
return messages, nil
51+
}
52+
2153
// NewGormMessageRepository creates the GORM version of the MessageRepository
2254
func NewGormMessageRepository(
2355
logger telemetry.Logger,

api/pkg/repositories/message_repository.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,7 @@ type MessageRepository interface {
1414

1515
// Load an entities.Message by ID
1616
Load(ctx context.Context, messageID uuid.UUID) (*entities.Message, error)
17+
18+
// GetOutstanding fetches list of outstanding []entities.Message
19+
GetOutstanding(ctx context.Context, take int) (*[]entities.Message, error)
1720
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package requests
2+
3+
import (
4+
"strconv"
5+
"strings"
6+
7+
"github.com/NdoleStudio/http-sms-manager/pkg/services"
8+
)
9+
10+
// MessageOutstanding is the payload fetching outstanding entities.Message
11+
type MessageOutstanding struct {
12+
Take string `json:"take" query:"take"`
13+
}
14+
15+
// Sanitize sets defaults to MessageOutstanding
16+
func (input *MessageOutstanding) Sanitize() MessageOutstanding {
17+
if strings.TrimSpace(input.Take) == "" {
18+
input.Take = "1"
19+
}
20+
return *input
21+
}
22+
23+
// ToGetOutstandingParams converts request to services.MessageGetOutstandingParams
24+
func (input *MessageOutstanding) ToGetOutstandingParams(source string) services.MessageGetOutstandingParams {
25+
return services.MessageGetOutstandingParams{
26+
Source: source,
27+
Take: input.getTake(),
28+
}
29+
}
30+
31+
// getTake gets the take as a string
32+
func (input *MessageOutstanding) getTake() int {
33+
val, _ := strconv.Atoi(input.Take)
34+
return val
35+
}

0 commit comments

Comments
 (0)