Fix sending buffered messages

This commit is contained in:
max-klaus 2020-01-26 21:35:07 +03:00
parent e6c0d55c95
commit c64b29a2a7
2 changed files with 55 additions and 43 deletions

View file

@ -9,6 +9,7 @@ import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan import android.text.style.ForegroundColorSpan
import net.osmand.PlatformUtil import net.osmand.PlatformUtil
import net.osmand.telegram.helpers.OsmandAidlHelper import net.osmand.telegram.helpers.OsmandAidlHelper
import net.osmand.telegram.helpers.ShareLocationHelper.Companion.MAX_MESSAGES_IN_TDLIB_PER_CHAT
import net.osmand.telegram.helpers.ShowLocationHelper import net.osmand.telegram.helpers.ShowLocationHelper
import net.osmand.telegram.helpers.TelegramHelper import net.osmand.telegram.helpers.TelegramHelper
import net.osmand.telegram.utils.* import net.osmand.telegram.utils.*
@ -22,6 +23,7 @@ import java.util.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.ConcurrentLinkedQueue
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.math.max
val ADDITIONAL_ACTIVE_TIME_VALUES_SEC = listOf(15 * 60L, 30 * 60L, 60 * 60L, 180 * 60L) val ADDITIONAL_ACTIVE_TIME_VALUES_SEC = listOf(15 * 60L, 30 * 60L, 60 * 60L, 180 * 60L)
@ -529,6 +531,7 @@ class TelegramSettings(private val app: TelegramApplication) {
var initializing = false var initializing = false
var sendChatsErrors = false var sendChatsErrors = false
val chatsCount = shareChatsInfo.size
shareChatsInfo.forEach { (_, shareInfo) -> shareChatsInfo.forEach { (_, shareInfo) ->
val initTime = (currentTime - shareInfo.start) < SHARING_INITIALIZATION_TIME val initTime = (currentTime - shareInfo.start) < SHARING_INITIALIZATION_TIME
var initSending = false var initSending = false
@ -537,15 +540,16 @@ class TelegramSettings(private val app: TelegramApplication) {
if (initTime && initSending) { if (initTime && initSending) {
initializing = true initializing = true
} else { } else {
val textSharingError = !shareInfo.lastTextMessageHandled && currentTime - shareInfo.lastSendTextMessageTime > WAITING_TDLIB_TIME val maxWaitingTime = WAITING_TDLIB_TIME * MAX_MESSAGES_IN_TDLIB_PER_CHAT * max(1, chatsCount)
val mapSharingError = !shareInfo.lastMapMessageHandled && currentTime - shareInfo.lastSendMapMessageTime > WAITING_TDLIB_TIME val textSharingError = !shareInfo.lastTextMessageHandled && currentTime - shareInfo.lastSendTextMessageTime > maxWaitingTime
val mapSharingError = !shareInfo.lastMapMessageHandled && currentTime - shareInfo.lastSendMapMessageTime > maxWaitingTime
if (shareInfo.hasSharingError if (shareInfo.hasSharingError
|| (shareTypeValue == SHARE_TYPE_MAP_AND_TEXT && (textSharingError || mapSharingError)) || (shareTypeValue == SHARE_TYPE_MAP_AND_TEXT && (textSharingError || mapSharingError))
|| textSharingError && (shareTypeValue == SHARE_TYPE_TEXT) || textSharingError && (shareTypeValue == SHARE_TYPE_TEXT)
|| mapSharingError && (shareTypeValue == SHARE_TYPE_MAP) || mapSharingError && (shareTypeValue == SHARE_TYPE_MAP)
) { ) {
sendChatsErrors = true sendChatsErrors = true
locationTime = Math.max(shareInfo.lastTextSuccessfulSendTime, shareInfo.lastMapSuccessfulSendTime) locationTime = max(shareInfo.lastTextSuccessfulSendTime, shareInfo.lastMapSuccessfulSendTime)
chatsIds.add(shareInfo.chatId) chatsIds.add(shareInfo.chatId)
} }
} }
@ -1455,6 +1459,7 @@ class TelegramSettings(private val app: TelegramApplication) {
var additionalActiveTime = ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0] var additionalActiveTime = ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]
var lastMapMessageHandled = false var lastMapMessageHandled = false
var lastTextMessageHandled = false var lastTextMessageHandled = false
var lastBufferCheckTime = -1L
fun getNextAdditionalActiveTime(): Long { fun getNextAdditionalActiveTime(): Long {
var index = ADDITIONAL_ACTIVE_TIME_VALUES_SEC.indexOf(additionalActiveTime) var index = ADDITIONAL_ACTIVE_TIME_VALUES_SEC.indexOf(additionalActiveTime)
@ -1469,6 +1474,13 @@ class TelegramSettings(private val app: TelegramApplication) {
return userSetLivePeriod - ((System.currentTimeMillis() / 1000) - start) return userSetLivePeriod - ((System.currentTimeMillis() / 1000) - start)
} }
fun isPendingMessagesLimitReached() =
pendingTdLibText >= MAX_MESSAGES_IN_TDLIB_PER_CHAT || pendingTdLibMap >= MAX_MESSAGES_IN_TDLIB_PER_CHAT
fun isPendingTextMessagesLimitReached() = pendingTdLibText >= MAX_MESSAGES_IN_TDLIB_PER_CHAT
fun isPendingMapMessagesLimitReached() = pendingTdLibMap >= MAX_MESSAGES_IN_TDLIB_PER_CHAT
companion object { companion object {
internal const val CHAT_ID_KEY = "chatId" internal const val CHAT_ID_KEY = "chatId"

View file

@ -15,24 +15,25 @@ import org.json.JSONObject
private const val USER_SET_LIVE_PERIOD_DELAY_MS = 5000 // 5 sec private const val USER_SET_LIVE_PERIOD_DELAY_MS = 5000 // 5 sec
private const val SENT_LOCATIONS_INTERVAL_TIME_MS = 4000 // 4 sec private const val MIN_MESSAGE_SENDING_INTERVAL_MS = 1000 // 1 sec
private const val MIN_MESSAGES_BUFFER_CHECK_INTERVAL_MS = 800 // 0.8 sec
class ShareLocationHelper(private val app: TelegramApplication) { class ShareLocationHelper(private val app: TelegramApplication) {
private val log = PlatformUtil.getLog(ShareLocationHelper::class.java) private val log = PlatformUtil.getLog(ShareLocationHelper::class.java)
var sharingLocation: Boolean = false var sharingLocation = false
private set private set
var duration: Long = 0 var duration = 0L
private set private set
var distance: Int = 0 var distance = 0
private set private set
var lastLocationUpdateTime: Long = 0 var lastLocationUpdateTime = 0L
var lastLocationSentTime: Long = 0 private var lastShareLocationMessageTime = 0L
var lastLocation: Location? = null var lastLocation: Location? = null
set(value) { set(value) {
@ -121,29 +122,32 @@ class ShareLocationHelper(private val app: TelegramApplication) {
fun checkAndSendBufferMessages() { fun checkAndSendBufferMessages() {
log.debug("checkAndSendBufferMessages") log.debug("checkAndSendBufferMessages")
var bufferedMessagesFull = false var pendingMessagesLimitReached = false
app.settings.getChatsShareInfo().forEach { (chatId, shareInfo) -> app.settings.getChatsShareInfo().forEach { (chatId, shareInfo) ->
checkAndSendBufferMessagesToChat(chatId) checkAndSendBufferMessagesToChat(chatId, true)
if (shareInfo.pendingTdLibText >= MAX_MESSAGES_IN_TDLIB_PER_CHAT || shareInfo.pendingTdLibMap >= MAX_MESSAGES_IN_TDLIB_PER_CHAT) { if (shareInfo.isPendingMessagesLimitReached()) {
bufferedMessagesFull = true pendingMessagesLimitReached = true
} }
} }
if (bufferedMessagesFull) { if (pendingMessagesLimitReached) {
checkNetworkType() checkNetworkType()
} }
} }
fun checkAndSendBufferMessagesToChat(chatId: Long) { fun checkAndSendBufferMessagesToChat(chatId: Long, forced: Boolean = false): Int {
val shareChatsInfo = app.settings.getChatsShareInfo() val shareChatsInfo = app.settings.getChatsShareInfo()
val shareInfo = shareChatsInfo[chatId] val shareInfo = shareChatsInfo[chatId]
val chatsCounts = shareChatsInfo.size if (shareInfo != null) {
val currentTime = System.currentTimeMillis() val currentTime = System.currentTimeMillis()
if (shareInfo != null && currentTime - lastLocationSentTime > chatsCounts * SENT_LOCATIONS_INTERVAL_TIME_MS) { if (currentTime - shareInfo.lastBufferCheckTime < MIN_MESSAGES_BUFFER_CHECK_INTERVAL_MS && !forced) {
return app.locationMessages.getBufferedMessagesCountForChat(chatId)
}
shareInfo.lastBufferCheckTime = currentTime
app.locationMessages.getBufferedTextMessagesForChat(chatId).take(MAX_MESSAGES_IN_TDLIB_PER_CHAT).forEach { app.locationMessages.getBufferedTextMessagesForChat(chatId).take(MAX_MESSAGES_IN_TDLIB_PER_CHAT).forEach {
if (shareInfo.pendingTdLibText < MAX_MESSAGES_IN_TDLIB_PER_CHAT) { if (!shareInfo.isPendingTextMessagesLimitReached()) {
if (it.deviceName.isEmpty()) { if (it.deviceName.isEmpty()) {
if (!shareInfo.pendingTextMessage && shareInfo.currentTextMessageId != -1L) { if (!shareInfo.pendingTextMessage && shareInfo.currentTextMessageId != -1L) {
lastLocationSentTime = System.currentTimeMillis()
val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, it, app) val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, it, app)
app.telegramHelper.editTextLocation(shareInfo, content) app.telegramHelper.editTextLocation(shareInfo, content)
app.locationMessages.removeBufferedMessage(it) app.locationMessages.removeBufferedMessage(it)
@ -154,10 +158,9 @@ class ShareLocationHelper(private val app: TelegramApplication) {
} }
} }
app.locationMessages.getBufferedMapMessagesForChat(chatId).take(MAX_MESSAGES_IN_TDLIB_PER_CHAT).forEach { app.locationMessages.getBufferedMapMessagesForChat(chatId).take(MAX_MESSAGES_IN_TDLIB_PER_CHAT).forEach {
if (shareInfo.pendingTdLibMap < MAX_MESSAGES_IN_TDLIB_PER_CHAT) { if (!shareInfo.isPendingMapMessagesLimitReached()) {
if (it.deviceName.isEmpty()) { if (it.deviceName.isEmpty()) {
if (!shareInfo.pendingMapMessage && shareInfo.currentMapMessageId != -1L) { if (!shareInfo.pendingMapMessage && shareInfo.currentMapMessageId != -1L) {
lastLocationSentTime = System.currentTimeMillis()
app.telegramHelper.editMapLocation(shareInfo, it) app.telegramHelper.editMapLocation(shareInfo, it)
app.locationMessages.removeBufferedMessage(it) app.locationMessages.removeBufferedMessage(it)
} }
@ -166,7 +169,9 @@ class ShareLocationHelper(private val app: TelegramApplication) {
} }
} }
} }
return app.locationMessages.getBufferedMessagesCountForChat(chatId)
} }
return 0
} }
fun startSharingLocation() { fun startSharingLocation() {
@ -219,44 +224,44 @@ class ShareLocationHelper(private val app: TelegramApplication) {
val time = location.time val time = location.time
val isBot = app.settings.currentSharingMode != userId.toString() val isBot = app.settings.currentSharingMode != userId.toString()
val deviceName = if (isBot) app.settings.currentSharingMode else "" val deviceName = if (isBot) app.settings.currentSharingMode else ""
var bufferedMessagesFull = false var pendingMessagesLimitReached = false
val chatsCounts = chatsShareInfo.size
val currentTime = System.currentTimeMillis() val currentTime = System.currentTimeMillis()
app.locationMessages.addMyLocationMessage(location) app.locationMessages.addMyLocationMessage(location)
if (currentTime - lastLocationSentTime <= chatsCounts * SENT_LOCATIONS_INTERVAL_TIME_MS) { if (currentTime - lastShareLocationMessageTime < MIN_MESSAGE_SENDING_INTERVAL_MS) {
return return
} }
lastShareLocationMessageTime = currentTime
chatsShareInfo.values.forEach { shareInfo -> chatsShareInfo.values.forEach { shareInfo ->
if (shareInfo.pendingTdLibText >= MAX_MESSAGES_IN_TDLIB_PER_CHAT || shareInfo.pendingTdLibMap >= MAX_MESSAGES_IN_TDLIB_PER_CHAT) { val hasBufferedMessages = checkAndSendBufferMessagesToChat(shareInfo.chatId) > 0
bufferedMessagesFull = true if (shareInfo.isPendingMessagesLimitReached()) {
pendingMessagesLimitReached = true
} }
checkAndSendBufferMessagesToChat(shareInfo.chatId)
when (app.settings.shareTypeValue) { when (app.settings.shareTypeValue) {
SHARE_TYPE_MAP -> { SHARE_TYPE_MAP -> {
val message = BufferMessage(shareInfo.chatId, latitude, longitude, altitude, speed, accuracy, bearing, time, LocationMessages.TYPE_MAP, deviceName) val message = BufferMessage(shareInfo.chatId, latitude, longitude, altitude, speed, accuracy, bearing, time, LocationMessages.TYPE_MAP, deviceName)
prepareMapMessage(shareInfo, message, isBot) prepareMapMessage(shareInfo, message, isBot, hasBufferedMessages)
} }
SHARE_TYPE_TEXT -> { SHARE_TYPE_TEXT -> {
val message = BufferMessage(shareInfo.chatId, latitude, longitude, altitude, speed, accuracy, bearing, time, LocationMessages.TYPE_TEXT, deviceName) val message = BufferMessage(shareInfo.chatId, latitude, longitude, altitude, speed, accuracy, bearing, time, LocationMessages.TYPE_TEXT, deviceName)
prepareTextMessage(shareInfo, message, isBot) prepareTextMessage(shareInfo, message, isBot, hasBufferedMessages)
} }
SHARE_TYPE_MAP_AND_TEXT -> { SHARE_TYPE_MAP_AND_TEXT -> {
val messageMap = BufferMessage(shareInfo.chatId, latitude, longitude, altitude, speed, accuracy, bearing, time, LocationMessages.TYPE_MAP, deviceName) val messageMap = BufferMessage(shareInfo.chatId, latitude, longitude, altitude, speed, accuracy, bearing, time, LocationMessages.TYPE_MAP, deviceName)
val messageText = BufferMessage(shareInfo.chatId, latitude, longitude, altitude, speed, accuracy, bearing, time, LocationMessages.TYPE_TEXT, deviceName) val messageText = BufferMessage(shareInfo.chatId, latitude, longitude, altitude, speed, accuracy, bearing, time, LocationMessages.TYPE_TEXT, deviceName)
prepareMapMessage(shareInfo, messageMap, isBot) prepareMapMessage(shareInfo, messageMap, isBot, hasBufferedMessages)
prepareTextMessage(shareInfo, messageText, isBot) prepareTextMessage(shareInfo, messageText, isBot, hasBufferedMessages)
} }
} }
} }
if (bufferedMessagesFull) { if (pendingMessagesLimitReached) {
checkNetworkType() checkNetworkType()
} }
} }
private fun prepareTextMessage(shareInfo: TelegramSettings.ShareChatInfo, message: BufferMessage, isBot: Boolean) { private fun prepareTextMessage(shareInfo: TelegramSettings.ShareChatInfo, message: BufferMessage, isBot: Boolean, hasBufferedMessages: Boolean) {
log.debug("prepareTextMessage $message") log.debug("prepareTextMessage $message")
if (shareInfo.currentTextMessageId == -1L) { if (shareInfo.currentTextMessageId == -1L) {
if (shareInfo.pendingTextMessage) { if (shareInfo.pendingTextMessage) {
@ -265,7 +270,6 @@ class ShareLocationHelper(private val app: TelegramApplication) {
if (isBot) { if (isBot) {
sendLocationToBot(message, shareInfo, SHARE_TYPE_TEXT) sendLocationToBot(message, shareInfo, SHARE_TYPE_TEXT)
} else { } else {
lastLocationSentTime = System.currentTimeMillis()
val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, message, app) val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, message, app)
app.telegramHelper.sendNewTextLocation(shareInfo, content) app.telegramHelper.sendNewTextLocation(shareInfo, content)
} }
@ -278,8 +282,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
app.locationMessages.addBufferedMessage(message) app.locationMessages.addBufferedMessage(message)
} }
} else { } else {
if (shareInfo.pendingTdLibText < MAX_MESSAGES_IN_TDLIB_PER_CHAT) { if (!shareInfo.isPendingTextMessagesLimitReached() && !hasBufferedMessages) {
lastLocationSentTime = System.currentTimeMillis()
val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, message, app) val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, message, app)
app.telegramHelper.editTextLocation(shareInfo, content) app.telegramHelper.editTextLocation(shareInfo, content)
} else { } else {
@ -289,7 +292,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
} }
} }
private fun prepareMapMessage(shareInfo: TelegramSettings.ShareChatInfo, message: BufferMessage, isBot: Boolean) { private fun prepareMapMessage(shareInfo: TelegramSettings.ShareChatInfo, message: BufferMessage, isBot: Boolean, hasBufferedMessages: Boolean) {
log.debug("prepareMapMessage $message") log.debug("prepareMapMessage $message")
if (shareInfo.currentMapMessageId == -1L) { if (shareInfo.currentMapMessageId == -1L) {
if (shareInfo.pendingMapMessage) { if (shareInfo.pendingMapMessage) {
@ -302,7 +305,6 @@ class ShareLocationHelper(private val app: TelegramApplication) {
app.locationMessages.addBufferedMessage(message) app.locationMessages.addBufferedMessage(message)
} }
} else { } else {
lastLocationSentTime = System.currentTimeMillis()
app.telegramHelper.sendNewMapLocation(shareInfo, message) app.telegramHelper.sendNewMapLocation(shareInfo, message)
} }
} }
@ -314,8 +316,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
app.locationMessages.addBufferedMessage(message) app.locationMessages.addBufferedMessage(message)
} }
} else { } else {
if (shareInfo.pendingTdLibMap < MAX_MESSAGES_IN_TDLIB_PER_CHAT) { if (!shareInfo.isPendingMapMessagesLimitReached() && !hasBufferedMessages) {
lastLocationSentTime = System.currentTimeMillis()
app.telegramHelper.editMapLocation(shareInfo, message) app.telegramHelper.editMapLocation(shareInfo, message)
} else { } else {
app.locationMessages.addBufferedMessage(message) app.locationMessages.addBufferedMessage(message)
@ -344,7 +345,6 @@ class ShareLocationHelper(private val app: TelegramApplication) {
} else if (shareType == SHARE_TYPE_MAP) { } else if (shareType == SHARE_TYPE_MAP) {
shareInfo.lastSendMapMessageTime = (System.currentTimeMillis() / 1000).toInt() shareInfo.lastSendMapMessageTime = (System.currentTimeMillis() / 1000).toInt()
} }
lastLocationSentTime = System.currentTimeMillis()
AndroidNetworkUtils.sendRequestAsync(app, url, null, "Send Location", false, false, AndroidNetworkUtils.sendRequestAsync(app, url, null, "Send Location", false, false,
object : AndroidNetworkUtils.OnRequestResultListener { object : AndroidNetworkUtils.OnRequestResultListener {
override fun onResult(result: String?) { override fun onResult(result: String?) {
@ -408,7 +408,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
companion object { companion object {
const val MAX_MESSAGES_IN_TDLIB_PER_CHAT = 10 const val MAX_MESSAGES_IN_TDLIB_PER_CHAT = 5
// min and max values for the UI // min and max values for the UI
const val MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC = TelegramHelper.MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC - 1 const val MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC = TelegramHelper.MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC - 1