-
Bizning ma'lumotlar bazamizdagi barcha guruhlarda oldingi bajarilganidan keyin nashr etilgan yangi maqolalarni topadi.
Ushbu sxema kichikroq guruhlarni belgilaydi - faqat faol foydalanuvchilari bo'lganlar. O'sha paytda bu menga mantiqiy tuyuldi, ammo hozir tushundimki, ma'lum bir guruhga obuna bo'lgan faol foydalanuvchilar bor yoki yo'qligidan qat'i nazar, siz hali ham bot tomonidan qayta ishlangan so'nggi maqolani yangilab turishingiz kerak. Vaziyat yangi foydalanuvchi ushbu guruh o'chirilganidan keyin chop etilgan barcha maqolalarni darhol qabul qilganda paydo bo'lishi mumkin. Bu kutilgan xatti-harakat emas va bunga yo'l qo'ymaslik uchun hozirda faol foydalanuvchilari mavjud bo'lmagan guruhlarni ma'lumotlar bazasidan saqlashimiz kerak. -
Agar yangi maqolalar bo'lsa, ushbu guruhga faol obuna bo'lgan barcha foydalanuvchilar uchun xabarlar yarating. Agar yangi maqolalar bo'lmasa, biz shunchaki ishni yakunlaymiz.
FindNewArticleService:
package com.github.javarushcommunity.jrtb.service;
/**
* Service for finding new articles.
*/
public interface FindNewArticleService {
/**
* Find new articles and notify subscribers about it.
*/
void findNewArticles();
}
Juda oddiy, to'g'rimi? Bu uning mohiyati va barcha qiyinchiliklar amalga oshirishda bo'ladi:
package com.github.javarushcommunity.jrtb.service;
import com.github.javarushcommunity.jrtb.javarushclient.JavaRushPostClient;
import com.github.javarushcommunity.jrtb.javarushclient.dto.PostInfo;
import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class FindNewArticleServiceImpl implements FindNewArticleService {
public static final String JAVARUSH_WEB_POST_FORMAT = "https://javarush.com/groups/posts/%s";
private final GroupSubService groupSubService;
private final JavaRushPostClient javaRushPostClient;
private final SendBotMessageService sendMessageService;
@Autowired
public FindNewArticleServiceImpl(GroupSubService groupSubService,
JavaRushPostClient javaRushPostClient,
SendBotMessageService sendMessageService) {
this.groupSubService = groupSubService;
this.javaRushPostClient = javaRushPostClient;
this.sendMessageService = sendMessageService;
}
@Override
public void findNewArticles() {
groupSubService.findAll().forEach(gSub -> {
List<PostInfo> newPosts = javaRushPostClient.findNewPosts(gSub.getId(), gSub.getLastArticleId());
setNewLastArticleId(gSub, newPosts);
notifySubscribersAboutNewArticles(gSub, newPosts);
});
}
private void notifySubscribersAboutNewArticles(GroupSub gSub, List<PostInfo> newPosts) {
Collections.reverse(newPosts);
List<String> messagesWithNewArticles = newPosts.stream()
.map(post -> String.format("✨Вышла новая статья <b>%s</b> в группе <b>%s</b>.✨\n\n" +
"<b>Описание:</b> %s\n\n" +
"<b>Ссылка:</b> %s\n",
post.getTitle(), gSub.getTitle(), post.getDescription(), getPostUrl(post.getKey())))
.collect(Collectors.toList());
gSub.getUsers().stream()
.filter(TelegramUser::isActive)
.forEach(it -> sendMessageService.sendMessage(it.getChatId(), messagesWithNewArticles));
}
private void setNewLastArticleId(GroupSub gSub, List<PostInfo> newPosts) {
newPosts.stream().mapToInt(PostInfo::getId).max()
.ifPresent(id -> {
gSub.setLastArticleId(id);
groupSubService.save(gSub);
});
}
private String getPostUrl(String key) {
return String.format(JAVARUSH_WEB_POST_FORMAT, key);
}
}
Bu erda biz hamma narsani tartibda hal qilamiz:
-
groupService- dan foydalanib, biz ma'lumotlar bazasidagi barcha guruhlarni topamiz.
-
Keyin biz barcha guruhlarga tarqalamiz va har biri uchun oxirgi maqolada yaratilgan mijozni chaqiramiz - javaRushPostClient.findNewPosts .
-
Keyinchalik, setNewArticleId usulidan foydalanib , biz so'nggi yangi maqolamizning maqola identifikatorini yangilaymiz, shunda ma'lumotlar bazasi yangilarini qayta ishlaganimizni biladi.
-
Va GroupSub-da foydalanuvchilar to'plami mavjudligidan foydalanib, biz faollar orqali o'tamiz va yangi maqolalar haqida bildirishnomalar yuboramiz.
FindNewArticleJob yarating
Biz allaqachon SpringScheduler nima ekanligi haqida gapirgan edik, lekin buni tezda takrorlaymiz: bu biz belgilagan ma'lum bir vaqtda ishlaydigan fon jarayonini yaratish uchun Spring doirasidagi mexanizm. Buning uchun sizga nima kerak? Birinchi qadam, bizning bahorgi kirish sinfimizga @EnableScheduling izohini qo'shishdir :package com.github.javarushcommunity.jrtb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@SpringBootApplication
public class JavarushTelegramBotApplication {
public static void main(String[] args) {
SpringApplication.run(JavarushTelegramBotApplication.class, args);
}
}
Ikkinchi qadam sinf yaratish, uni ApplicationContext- ga qo'shish va unda vaqti-vaqti bilan bajariladigan usulni yaratishdir. Biz ombor, xizmat va boshqalar bilan bir xil darajadagi ish paketini yaratamiz va u erda FindNewArticleJob sinfini yaratamiz :
package com.github.javarushcommunity.jrtb.job;
import com.github.javarushcommunity.jrtb.service.FindNewArticleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
/**
* Job for finding new articles.
*/
@Slf4j
@Component
public class FindNewArticlesJob {
private final FindNewArticleService findNewArticleService;
@Autowired
public FindNewArticlesJob(FindNewArticleService findNewArticleService) {
this.findNewArticleService = findNewArticleService;
}
@Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}")
public void findNewArticles() {
LocalDateTime start = LocalDateTime.now();
log.info("Find new article job started.");
findNewArticleService.findNewArticles();
LocalDateTime end = LocalDateTime.now();
log.info("Find new articles job finished. Took seconds: {}",
end.toEpochSecond(ZoneOffset.UTC) - start.toEpochSecond(ZoneOffset.UTC));
}
}
Ushbu sinfni Ilova kontekstiga qo'shish uchun men @Component izohidan foydalandim . Va sinf ichidagi usul uni vaqti-vaqti bilan ishga tushirish kerakligini bilishi uchun men usulga izoh qo'shdim: @Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}") . Lekin biz uni application.properties faylida o'rnatdik:
bot.recountNewArticleFixedRate = 900000
Bu erda qiymat millisekundlarda. 15 daqiqa bo'ladi. Bu usulda hamma narsa oddiy: men hech bo'lmaganda uning qanchalik tez ishlashini tushunish uchun yangi maqolalarni qidirishni hisoblash uchun jurnallarga o'zim uchun juda oddiy ko'rsatkichni qo'shdim.
Yangi funksionallikni sinab ko'rish
Endi biz test botimizda sinab ko'ramiz. Lekin qanday? Bildirishnomalar kelganligini ko'rsatish uchun har safar maqolalarni o'chirmaymanmi? Albatta yo'q. Biz shunchaki ma'lumotlar bazasidagi ma'lumotlarni tahrir qilamiz va dasturni ishga tushiramiz. Men uni sinov serverimda sinab ko'raman. Buning uchun keling, qandaydir guruhga obuna bo'laylik. Obuna tugallangach, guruhga oxirgi maqolaning joriy identifikatori beriladi. Keling, ma'lumotlar bazasiga o'tamiz va ikki maqolaning qiymatini o'zgartiramiz. Natijada, biz lastArticleId ga avvalroq o'rnatganimizdek, shuncha maqola bo'lishini kutamiz . Keyinchalik, biz saytga o'tamiz, Java loyihalari guruhidagi maqolalarni saralaymiz - birinchi navbatda yangilari - va ro'yxatdagi uchinchi maqolaga o'tamiz: Pastki maqolaga o'tamiz va manzil satridan biz maqolani olamiz Id - 3313: Keyingi , MySQL Workbench-ga o'ting va lastArticleId qiymatini 3313 ga o'zgartiring. Keling, bunday guruh ma'lumotlar bazasida mavjudligini ko'rib chiqaylik: Va buning uchun biz buyruqni bajaramiz: Va tamom, endi ishning keyingi ishga tushirilishini kutish kerak. yangi maqolalarni qidiring. Java loyihalari guruhidan yangi maqola haqida ikkita xabar olishni kutamiz. Ular aytganidek, natija uzoq kutilgani yo'q: ma'lum bo'lishicha, bot biz kutgandek ishlagan.Tugatish
Har doimgidek, biz pom.xml versiyasini yangilaymiz va RELEASE_NOTES-ga yozuv qo'shamiz, shunda ish tarixi saqlanadi va siz har doim orqaga qaytib, nima o'zgarganini tushunishingiz mumkin. Shuning uchun biz versiyani bir birlikka oshiramiz:<version>0.7.0-SNAPSHOT</version>
Va RELEASE_NOTES-ni yangilang:
GO TO FULL VERSION