diff --git a/backend/src/main/java/net/buzzert/kordophone/backend/events/MessageDeliveredEvent.kt b/backend/src/main/java/net/buzzert/kordophone/backend/events/MessageDeliveredEvent.kt index eff9dd2..75e063d 100644 --- a/backend/src/main/java/net/buzzert/kordophone/backend/events/MessageDeliveredEvent.kt +++ b/backend/src/main/java/net/buzzert/kordophone/backend/events/MessageDeliveredEvent.kt @@ -1,9 +1,11 @@ package net.buzzert.kordophone.backend.events import net.buzzert.kordophone.backend.model.Conversation +import net.buzzert.kordophone.backend.model.GUID import net.buzzert.kordophone.backend.model.Message data class MessageDeliveredEvent( + val guid: GUID, val message: Message, val conversation: Conversation, ) diff --git a/backend/src/main/java/net/buzzert/kordophone/backend/model/Conversation.kt b/backend/src/main/java/net/buzzert/kordophone/backend/model/Conversation.kt index 44bef55..947f222 100644 --- a/backend/src/main/java/net/buzzert/kordophone/backend/model/Conversation.kt +++ b/backend/src/main/java/net/buzzert/kordophone/backend/model/Conversation.kt @@ -3,6 +3,8 @@ package net.buzzert.kordophone.backend.model import com.google.gson.annotations.SerializedName import java.util.Date +typealias GUID = String + data class Conversation( @SerializedName("date") val date: Date, @@ -20,5 +22,5 @@ data class Conversation( val lastMessagePreview: String, @SerializedName("guid") - val guid: String, + val guid: GUID, ) diff --git a/backend/src/main/java/net/buzzert/kordophone/backend/model/Message.kt b/backend/src/main/java/net/buzzert/kordophone/backend/model/Message.kt index 3aff5a4..283ad98 100644 --- a/backend/src/main/java/net/buzzert/kordophone/backend/model/Message.kt +++ b/backend/src/main/java/net/buzzert/kordophone/backend/model/Message.kt @@ -8,7 +8,7 @@ data class Message( val text: String, @SerializedName("guid") - val guid: String, + val guid: GUID, @SerializedName("sender") val sender: String?, // optional: nil means "from me" diff --git a/backend/src/main/java/net/buzzert/kordophone/backend/server/ChatRepository.kt b/backend/src/main/java/net/buzzert/kordophone/backend/server/ChatRepository.kt index ec549b1..adefe66 100644 --- a/backend/src/main/java/net/buzzert/kordophone/backend/server/ChatRepository.kt +++ b/backend/src/main/java/net/buzzert/kordophone/backend/server/ChatRepository.kt @@ -5,17 +5,25 @@ import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.runBlocking import net.buzzert.kordophone.backend.events.MessageDeliveredEvent import net.buzzert.kordophone.backend.model.Conversation +import net.buzzert.kordophone.backend.model.GUID import net.buzzert.kordophone.backend.model.Message import java.net.URL import java.util.Queue +import java.util.UUID import java.util.concurrent.ArrayBlockingQueue const val REPO_LOG: String = "ChatRepository" class ChatRepository(private val apiInterface: APIInterface) { - public val messageDeliveredChannel = Channel() + val messageDeliveredChannel = Channel() - private val outgoingMessageQueue: ArrayBlockingQueue> = ArrayBlockingQueue(16) + private data class OutgoingMessageInfo ( + val message: Message, + val conversation: Conversation, + val guid: GUID, + ) + + private val outgoingMessageQueue: ArrayBlockingQueue = ArrayBlockingQueue(16) private var outgoingMessageThread: Thread? = null suspend fun getVersion(): String { @@ -30,14 +38,18 @@ class ChatRepository(private val apiInterface: APIInterface) { return apiInterface.getMessages(conversation.guid).body()!! } - suspend fun enqueueOutgoingMessage(message: Message, conversation: Conversation) { - Log.d(REPO_LOG, "Enqueuing outgoing message: $message") - outgoingMessageQueue.add(Pair(message, conversation)) + suspend fun enqueueOutgoingMessage(message: Message, conversation: Conversation): GUID { + val guid = UUID.randomUUID().toString() + + Log.d(REPO_LOG, "Enqueuing outgoing message: $message ($guid)") + outgoingMessageQueue.add(OutgoingMessageInfo(message, conversation, guid)) if (outgoingMessageThread == null) { outgoingMessageThread = Thread { outgoingMessageQueueMain() } outgoingMessageThread?.start() } + + return guid } // - private @@ -47,7 +59,10 @@ class ChatRepository(private val apiInterface: APIInterface) { while (true) { val outgoingMessageRequest = outgoingMessageQueue.poll()?.let { runBlocking { - val (message, conversation) = it + val guid = it.guid + val message = it.message + val conversation = it.conversation + Log.d(REPO_LOG, "Sending message to $conversation: $message") val result = apiInterface.sendMessage( @@ -60,7 +75,7 @@ class ChatRepository(private val apiInterface: APIInterface) { if (result.isSuccessful) { Log.d(REPO_LOG, "Successfully sent message.") - messageDeliveredChannel.send(MessageDeliveredEvent(message, conversation)) + messageDeliveredChannel.send(MessageDeliveredEvent(guid, message, conversation)) } else { Log.e(REPO_LOG, "Error sending message. Enqueuing for retry.") outgoingMessageQueue.add(it) diff --git a/backend/src/test/java/net/buzzert/kordophone/backend/BackendTests.kt b/backend/src/test/java/net/buzzert/kordophone/backend/BackendTests.kt index 75992f3..1d77776 100644 --- a/backend/src/test/java/net/buzzert/kordophone/backend/BackendTests.kt +++ b/backend/src/test/java/net/buzzert/kordophone/backend/BackendTests.kt @@ -78,9 +78,10 @@ class BackendTests { sender = null, ) - repository.enqueueOutgoingMessage(outgoingMessage, conversation) + val guid = repository.enqueueOutgoingMessage(outgoingMessage, conversation) val event = repository.messageDeliveredChannel.receive() + assertEquals(event.guid, guid) assertEquals(event.message.text, outgoingMessage.text) } } \ No newline at end of file