Skip to content

Commit 67301a6

Browse files
committed
Fetching one message per outstanding reqeust
1 parent e2c3459 commit 67301a6

File tree

8 files changed

+53
-47
lines changed

8 files changed

+53
-47
lines changed

android/app/src/main/java/com/httpsms/FirebaseMessagingService.kt

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,25 @@ import android.app.PendingIntent
44
import android.content.Context
55
import android.content.Intent
66
import android.content.IntentFilter
7-
import androidx.work.OneTimeWorkRequest
8-
import androidx.work.WorkManager
9-
import androidx.work.Worker
10-
import androidx.work.WorkerParameters
7+
import androidx.work.*
118
import com.google.firebase.messaging.FirebaseMessagingService
129
import com.google.firebase.messaging.RemoteMessage
1310
import timber.log.Timber
1411

1512

1613
class MyFirebaseMessagingService : FirebaseMessagingService() {
17-
private val timberInit = false
18-
1914
// [START receive_message]
2015
override fun onMessageReceived(remoteMessage: RemoteMessage) {
2116
initTimber()
2217
Timber.d(MyFirebaseMessagingService::onMessageReceived.name)
23-
scheduleJob()
18+
19+
val messageID = remoteMessage.data[Constants.KEY_MESSAGE_ID]
20+
if (messageID == null) {
21+
Timber.e("cannot get message id from notification data with key [${Constants.KEY_MESSAGE_ID}]")
22+
return
23+
}
24+
25+
scheduleJob(messageID)
2426
}
2527
// [END receive_message]
2628

@@ -41,15 +43,20 @@ class MyFirebaseMessagingService : FirebaseMessagingService() {
4143
}
4244
// [END on_new_token]
4345

44-
private fun scheduleJob() {
46+
private fun scheduleJob(messageID: String) {
4547
// [START dispatch_job]
48+
val inputData: Data = workDataOf(Constants.KEY_MESSAGE_ID to messageID)
4649
val work = OneTimeWorkRequest
4750
.Builder(SendSmsWorker::class.java)
51+
.setInputData(inputData)
52+
.addTag(messageID)
4853
.build()
4954

5055
WorkManager
5156
.getInstance(this)
5257
.enqueue(work)
58+
59+
Timber.d("work enqueued with ID [${work.id}] for messageID [${messageID}]")
5360
// [END dispatch_job]
5461
}
5562
private fun sendRegistrationToServer(token: String) {
@@ -87,9 +94,13 @@ class MyFirebaseMessagingService : FirebaseMessagingService() {
8794
return Result.failure()
8895
}
8996

90-
val owner = Settings.getOwner(applicationContext) ?: return Result.failure()
91-
val message = getMessage(applicationContext, owner) ?: return Result.failure()
97+
val messageID = this.inputData.getString(Constants.KEY_MESSAGE_ID)
98+
if (messageID == null) {
99+
Timber.e("cannot get outstanding message for work [${this.id}]")
100+
return Result.failure()
101+
}
92102

103+
val message = getMessage(applicationContext, messageID) ?: return Result.failure()
93104
registerReceivers(applicationContext, message.id)
94105

95106
sendMessage(
@@ -112,16 +123,16 @@ class MyFirebaseMessagingService : FirebaseMessagingService() {
112123
)
113124
}
114125

115-
private fun getMessage(context: Context, owner: String): Message? {
116-
Timber.d("fetching message")
117-
val messages = HttpSmsApiService(Settings.getApiKeyOrDefault(context)).getOutstandingMessages(owner)
126+
private fun getMessage(context: Context, messageID: String): Message? {
127+
Timber.d("fetching message with ID [${messageID}]")
128+
val message = HttpSmsApiService(Settings.getApiKeyOrDefault(context)).getOutstandingMessage(messageID)
118129

119-
if (messages.isNotEmpty()) {
120-
Timber.d("fetched message with ID [${messages.first().id}]")
121-
return messages.first()
130+
if (message != null) {
131+
Timber.d("fetched message with ID [${message.id}]")
132+
return message
122133
}
123134

124-
Timber.e("cannot get message from API")
135+
Timber.e("cannot get message from API with ID [${messageID}]")
125136
return null
126137
}
127138

android/app/src/main/java/com/httpsms/HttpSmsApiService.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,36 @@ import java.util.logging.Logger.getLogger
1414

1515

1616
class HttpSmsApiService(private val apiKey: String) {
17-
private val apiKeyHeader = "X-API-KEY"
18-
private val baseURL = URI("https://api.httpsms.com")
17+
private val apiKeyHeader = "x-api-key"
18+
private val baseURL = URI("https://41f2-145-14-47-25.ngrok.io")
1919
private val jsonMediaType = "application/json; charset=utf-8".toMediaType()
2020

2121
init {
2222
getLogger(OkHttpClient::class.java.name).level = Level.FINE
2323
}
2424

25-
fun getOutstandingMessages(owner: String): List<Message> {
25+
fun getOutstandingMessage(messageID: String): Message? {
2626
val client = OkHttpClient()
2727

2828
val request: Request = Request.Builder()
29-
.url(baseURL.resolve("/v1/messages/outstanding?owner=${owner}").toURL())
29+
.url(baseURL.resolve("/v1/messages/outstanding?message_id=${messageID}").toURL())
3030
.header(apiKeyHeader, apiKey)
3131
.build()
3232

3333
val response = client.newCall(request).execute()
3434
if (response.isSuccessful) {
35-
val payload = ResponseMessagesOutstanding.fromJson(response.body!!.string())?.data
35+
val payload = ResponseMessage.fromJson(response.body!!.string())?.data
3636
if (payload == null) {
3737
Timber.e("cannot decode payload [${response.body}]")
38-
return listOf()
38+
return null
3939
}
4040
response.close()
4141
return payload
4242
}
4343

4444
Timber.e("invalid response with code [${response.code}] and payload [${response.body}]")
4545
response.close()
46-
return listOf()
46+
return null
4747
}
4848

4949
fun sendDeliveredEvent(messageId: String, timestamp: ZonedDateTime) {

android/app/src/main/java/com/httpsms/Models.kt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,6 @@ import com.beust.klaxon.Klaxon
99

1010
private val klaxon = Klaxon()
1111

12-
data class ResponseMessagesOutstanding (
13-
val data: List<Message>,
14-
val message: String,
15-
val status: String
16-
) {
17-
companion object {
18-
fun fromJson(json: String) = klaxon.parse<ResponseMessagesOutstanding>(json)
19-
}
20-
}
21-
2212
data class ResponseMessage (
2313
val data: Message,
2414
val message: String,

api/pkg/entities/message.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func (message *Message) Sent(timestamp time.Time) *Message {
9292
sendDuration := timestamp.UnixNano() - message.RequestReceivedAt.UnixNano()
9393
message.SentAt = &timestamp
9494
message.Status = MessageStatusSent
95-
message.OrderTimestamp = timestamp
95+
message.updateOrderTimestamp(timestamp)
9696
message.SendDuration = &sendDuration
9797
return message
9898
}
@@ -101,22 +101,28 @@ func (message *Message) Sent(timestamp time.Time) *Message {
101101
func (message *Message) Failed(timestamp time.Time) *Message {
102102
message.SentAt = &timestamp
103103
message.Status = MessageStatusFailed
104-
message.OrderTimestamp = timestamp
104+
message.updateOrderTimestamp(timestamp)
105105
return message
106106
}
107107

108108
// Delivered registers a message as delivered
109109
func (message *Message) Delivered(timestamp time.Time) *Message {
110110
message.SentAt = &timestamp
111111
message.Status = MessageStatusDelivered
112-
message.OrderTimestamp = timestamp
112+
message.updateOrderTimestamp(timestamp)
113113
return message
114114
}
115115

116116
// AddSendAttempt configures a Message for sending
117117
func (message *Message) AddSendAttempt(timestamp time.Time) *Message {
118118
message.Status = MessageStatusSending
119119
message.LastAttemptedAt = &timestamp
120-
message.OrderTimestamp = timestamp
120+
message.updateOrderTimestamp(timestamp)
121121
return message
122122
}
123+
124+
func (message *Message) updateOrderTimestamp(timestamp time.Time) {
125+
if timestamp.UnixNano() > message.OrderTimestamp.UnixNano() {
126+
message.OrderTimestamp = timestamp
127+
}
128+
}

api/pkg/middlewares/otel_context_middleware.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ func OtelTraceContext(tracer telemetry.Tracer, logger telemetry.Logger, header s
5858
response := c.Next()
5959

6060
statusCode := c.Response().StatusCode()
61-
span.AddEvent(fmt.Sprintf("finished handling request with traceID: %s, statusCode = %d", traceID, statusCode))
61+
span.AddEvent(fmt.Sprintf("finished handling request with traceID: [%s], statusCode: [%d]", traceID, statusCode))
6262

6363
if statusCode >= 300 && len(c.Request().Body()) > 0 {
64-
ctxLogger.Warn(stacktrace.NewError(fmt.Sprintf("http.status [%b], body [%s]", statusCode, string(c.Request().Body()))))
64+
ctxLogger.Warn(stacktrace.NewError(fmt.Sprintf("http.status [%d], body [%s]", statusCode, string(c.Request().Body()))))
6565
}
6666

6767
return response

api/pkg/repositories/gorm_message_repository.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func (repository *gormMessageRepository) Load(ctx context.Context, userID entiti
8080
message := new(entities.Message)
8181
err := repository.db.WithContext(ctx).Where("user_id = ?", userID).Where("id = ?", messageID).First(message).Error
8282
if errors.Is(err, gorm.ErrRecordNotFound) {
83-
msg := fmt.Sprintf("message with ID [%s] does not exist", message.ID)
83+
msg := fmt.Sprintf("message with ID [%s] and userID [%s] does not exist", messageID, userID)
8484
return nil, repository.tracer.WrapErrorSpan(span, stacktrace.PropagateWithCode(err, ErrCodeNotFound, msg))
8585
}
8686

api/pkg/services/message_service.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ func (service *MessageService) handleMessageDeliveredEvent(ctx context.Context,
244244
event, err := service.createMessagePhoneDeliveredEvent(params.Source, events.MessagePhoneDeliveredPayload{
245245
ID: message.ID,
246246
Owner: message.Owner,
247+
UserID: message.UserID,
247248
Timestamp: params.Timestamp,
248249
Contact: message.Contact,
249250
Content: message.Content,
@@ -514,8 +515,8 @@ func (service *MessageService) HandleMessageDelivered(ctx context.Context, param
514515
return service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
515516
}
516517

517-
if !message.IsSent() {
518-
msg := fmt.Sprintf("message has wrong status [%s]. expected %s", message.Status, entities.MessageStatusSent)
518+
if !message.IsSent() && !message.IsSending() {
519+
msg := fmt.Sprintf("message has wrong status [%s]. expected [%s, %s]", message.Status, entities.MessageStatusSent, entities.MessageStatusSending)
519520
return service.tracer.WrapErrorSpan(span, stacktrace.NewError(msg))
520521
}
521522

api/pkg/validators/phone_handler_validator.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,11 @@ func (validator *PhoneHandlerValidator) ValidateUpsert(_ context.Context, reques
6262
phoneNumberRule,
6363
},
6464
"fcm_token": []string{
65-
"required",
66-
"min:1",
65+
"min:0",
6766
"max:1000",
6867
},
6968
"messages_per_minute": []string{
70-
"required",
71-
"min:1",
69+
"min:0",
7270
"max:60",
7371
},
7472
},

0 commit comments

Comments
 (0)