add retryOnPostFailureTimes

This commit is contained in:
InsanusMokrassar 2023-11-06 19:18:19 +06:00
parent 947bd7c2c4
commit 0cc0510876
5 changed files with 43 additions and 14 deletions

View File

@ -11,7 +11,6 @@ import dev.inmo.tgbotapi.extensions.api.send.copyMessage
import dev.inmo.tgbotapi.extensions.api.send.send import dev.inmo.tgbotapi.extensions.api.send.send
import dev.inmo.tgbotapi.extensions.utils.* import dev.inmo.tgbotapi.extensions.utils.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
import dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent import dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent
class PostPublisher( class PostPublisher(
@ -21,10 +20,10 @@ class PostPublisher(
private val targetChatIds: List<IdChatIdentifier>, private val targetChatIds: List<IdChatIdentifier>,
private val deleteAfterPosting: Boolean = true private val deleteAfterPosting: Boolean = true
) { ) {
suspend fun publish(postId: PostId) { suspend fun publish(postId: PostId): Boolean {
val messagesInfo = postsRepo.getById(postId) ?: let { val messagesInfo = postsRepo.getById(postId) ?: let {
logger.w { "Unable to get post with id $postId for publishing" } logger.w { "Unable to get post with id $postId for publishing" }
return return false
} }
val sortedMessagesContents = messagesInfo.content.groupBy { it.group }.flatMap { (group, list) -> val sortedMessagesContents = messagesInfo.content.groupBy { it.group }.flatMap { (group, list) ->
if (group == null) { if (group == null) {
@ -35,6 +34,7 @@ class PostPublisher(
listOf(list.first().order to list) listOf(list.first().order to list)
} }
}.sortedBy { it.first } }.sortedBy { it.first }
var haveSentMessages = false
sortedMessagesContents.forEach { (_, contents) -> sortedMessagesContents.forEach { (_, contents) ->
contents.singleOrNull() ?.also { contents.singleOrNull() ?.also {
@ -44,13 +44,16 @@ class PostPublisher(
}.onFailure { _ -> }.onFailure { _ ->
runCatching { runCatching {
bot.forwardMessage( bot.forwardMessage(
it.chatId, fromChatId = it.chatId,
targetChatId, toChatId = cachingChatId,
it.messageId messageId = it.messageId
) )
}.onSuccess { }.onSuccess {
bot.copyMessage(targetChatId, it) bot.copyMessage(targetChatId, it)
haveSentMessages = true
} }
}.onSuccess {
haveSentMessages = true
} }
} }
return@forEach return@forEach
@ -61,12 +64,14 @@ class PostPublisher(
forwardedMessage.withContentOrNull<MediaGroupPartContent>() ?: null.also { _ -> forwardedMessage.withContentOrNull<MediaGroupPartContent>() ?: null.also { _ ->
targetChatIds.forEach { targetChatId -> targetChatIds.forEach { targetChatId ->
bot.copyMessage(targetChatId, forwardedMessage) bot.copyMessage(targetChatId, forwardedMessage)
haveSentMessages = true
} }
} }
} }
resultContents.singleOrNull() ?.also { resultContents.singleOrNull() ?.also {
targetChatIds.forEach { targetChatId -> targetChatIds.forEach { targetChatId ->
bot.copyMessage(targetChatId, it) bot.copyMessage(targetChatId, it)
haveSentMessages = true
} }
return@forEach return@forEach
} ?: resultContents.chunked(mediaCountInMediaGroup.last).forEach { } ?: resultContents.chunked(mediaCountInMediaGroup.last).forEach {
@ -75,6 +80,7 @@ class PostPublisher(
targetChatId, targetChatId,
it.map { it.content.toMediaGroupMemberTelegramMedia() } it.map { it.content.toMediaGroupMemberTelegramMedia() }
) )
haveSentMessages = true
} }
} }
} }
@ -83,5 +89,6 @@ class PostPublisher(
postsRepo.deleteById(postId) postsRepo.deleteById(postId)
} }
return haveSentMessages
} }
} }

View File

@ -5,4 +5,9 @@ import dev.inmo.plaguposter.posts.models.PostId
interface Selector { interface Selector {
suspend fun take(n: Int = 1, now: DateTime = DateTime.now(), exclude: List<PostId> = emptyList()): List<PostId> suspend fun take(n: Int = 1, now: DateTime = DateTime.now(), exclude: List<PostId> = emptyList()): List<PostId>
suspend fun takeOneOrNull(now: DateTime = DateTime.now(), exclude: List<PostId> = emptyList()): PostId? = take(
n = 1,
now = now,
exclude = exclude
).firstOrNull()
} }

View File

@ -65,7 +65,9 @@
] ]
}, },
"timer_trigger": { "timer_trigger": {
"krontab": "0 30 2/4 * *" "krontab": "0 30 2/4 * *",
"retryOnPostFailureTimes": 0,
"_note": "retryOnPostFailureTimes will retry to publish one or several posts if posting has been failed"
}, },
"panel": { "panel": {
"textPrefix": "Post management:", "textPrefix": "Post management:",

View File

@ -77,7 +77,7 @@ object Plugin : Plugin {
return@onCommand return@onCommand
} }
} ?: selector ?.take(1) ?.firstOrNull() } ?: selector ?.takeOneOrNull()
if (postId == null) { if (postId == null) {
reply( reply(
it, it,

View File

@ -51,7 +51,8 @@ object Plugin : Plugin {
internal data class Config( internal data class Config(
@SerialName("krontab") @SerialName("krontab")
val krontabTemplate: KrontabTemplate, val krontabTemplate: KrontabTemplate,
val dateTimeFormat: String = "HH:mm:ss, dd.MM.yyyy" val dateTimeFormat: String = "HH:mm:ss, dd.MM.yyyy",
val retryOnPostFailureTimes: Int = 0
) { ) {
@Transient @Transient
val krontab by lazy { val krontab by lazy {
@ -88,13 +89,27 @@ object Plugin : Plugin {
} }
val krontab = koin.get<Config>().krontab val krontab = koin.get<Config>().krontab
val retryOnPostFailureTimes = koin.get<Config>().retryOnPostFailureTimes
val dateTimeFormat = koin.get<Config>().format val dateTimeFormat = koin.get<Config>().format
krontab.asFlowWithDelays().subscribeSafelyWithoutExceptions(this) { dateTime -> krontab.asFlowWithDelays().subscribeSafelyWithoutExceptions(this) { dateTime ->
selector.take(now = dateTime).forEach { postId -> var leftRetries = retryOnPostFailureTimes
do {
val success = runCatching {
selector.takeOneOrNull(now = dateTime) ?.let { postId ->
if (filters.all { it.check(postId, dateTime) }) { if (filters.all { it.check(postId, dateTime) }) {
publisher.publish(postId) publisher.publish(postId)
} else {
false
} }
} ?: false
}.getOrElse {
false
} }
if (success) {
break;
}
leftRetries--;
} while (leftRetries > 0)
} }
suspend fun buildPage(pagination: Pagination = FirstPagePagination(size = pageCallbackDataQuerySize)): InlineKeyboardMarkup { suspend fun buildPage(pagination: Pagination = FirstPagePagination(size = pageCallbackDataQuerySize)): InlineKeyboardMarkup {
@ -113,7 +128,7 @@ object Plugin : Plugin {
val selected = mutableListOf<PostId>() val selected = mutableListOf<PostId>()
krontab.asFlowWithoutDelays().take(pagination.lastIndexExclusive).collectIndexed { i, dateTime -> krontab.asFlowWithoutDelays().take(pagination.lastIndexExclusive).collectIndexed { i, dateTime ->
val postId = selector.take(now = dateTime, exclude = selected).firstOrNull() ?.also { postId -> val postId = selector.takeOneOrNull(now = dateTime, exclude = selected) ?.also { postId ->
if (filters.all { it.check(postId, dateTime) }) { if (filters.all { it.check(postId, dateTime) }) {
selected.add(postId) selected.add(postId)
} else { } else {