-
Verilənlər bazamızda olan bütün qruplarda əvvəlki icradan sonra dərc edilmiş yeni məqalələri tapır.
Bu sxem daha az sayda qrupları müəyyən edir - yalnız aktiv istifadəçiləri olanlar. O vaxt mənə məntiqli görünürdü, amma indi başa düşürəm ki, konkret qrupa abunə olan aktiv istifadəçilərin olub-olmamasından asılı olmayaraq, siz hələ də botun işlədiyi ən son məqaləni aktual saxlamalısınız. Yeni istifadəçi bu qrup ləğv edildikdən sonra dərc edilmiş məqalələrin bütün sayını dərhal aldıqda vəziyyət yarana bilər. Bu gözlənilən davranış deyil və bunun qarşısını almaq üçün hazırda aktiv istifadəçiləri olmayan qrupları bazamızda saxlamalıyıq. -
Yeni məqalələr varsa, bu qrupa aktiv şəkildə abunə olan bütün istifadəçilər üçün mesajlar yaradın. Yeni məqalələr yoxdursa, sadəcə işi tamamlayırıq.
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();
}
Çox sadə, elə deyilmi? Bu, onun mahiyyətidir və bütün çətinlik icrada olacaq:
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);
}
}
Burada hər şeyi qaydasında həll edəcəyik:
-
groupService istifadə edərək verilənlər bazasında olan bütün qrupları tapırıq.
-
Sonra bütün qruplara dağılırıq və hər biri üçün son məqalədə yaradılmış müştəri çağırırıq - javaRushPostClient.findNewPosts .
-
Sonra, setNewArticleId metodundan istifadə edərək , ən son yeni məqaləmizin məqalə identifikatorunu yeniləyirik ki, verilənlər bazamız artıq yenilərini emal etdiyimizi bilsin.
-
Və GroupSub-un istifadəçilər toplusuna malik olması faktından istifadə edərək, biz aktiv olanlardan keçirik və yeni məqalələr haqqında bildirişlər göndəririk.
FindNewArticleJob yaradın
SpringScheduler-in nə olduğu haqqında artıq danışdıq, lakin gəlin bunu tez bir zamanda təkrarlayaq: bu, bizim təyin etdiyimiz müəyyən vaxtda işləyəcək fon prosesi yaratmaq üçün Bahar çərçivəsindəki mexanizmdir. Bunun üçün sizə nə lazımdır? İlk addım yaz giriş sinifimizə @EnableScheduling annotasiyasını əlavə etməkdir :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);
}
}
İkinci addım sinif yaratmaq, onu ApplicationContext- ə əlavə etmək və orada vaxtaşırı işlədilən metod yaratmaqdır. Biz repozitoriya, xidmət və s. ilə eyni səviyyədə iş paketi yaradırıq və orada FindNewArticleJob sinfini yaradırıq :
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));
}
}
Bu sinfi Tətbiq Kontekstinə əlavə etmək üçün @Component annotasiyasından istifadə etdim . Sinif daxilindəki metodun onun vaxtaşırı işə salınması lazım olduğunu bilməsi üçün metoda annotasiya əlavə etdim: @Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}") . Amma biz bunu application.properties faylında təyin etdik:
bot.recountNewArticleFixedRate = 900000
Burada dəyər millisaniyədədir. 15 dəqiqə olacaq. Bu üsulda hər şey sadədir: yeni məqalələrin axtarışını hesablamaq üçün qeydlərə özüm üçün super sadə bir metrik əlavə etdim ki, heç olmasa onun nə qədər sürətli işlədiyini başa düşsün.
Yeni funksionallığın sınaqdan keçirilməsi
İndi test botumuzda test edəcəyik. Bəs necə? Bildirişlərin gəldiyini göstərmək üçün hər dəfə məqalələri silməyəcəyəm? Əlbəttə yox. Biz sadəcə olaraq verilənlər bazasındakı məlumatları redaktə edəcəyik və proqramı işə salacağıq. Test serverimdə sınaqdan keçirəcəyəm. Bunun üçün gəlin hansısa qrupa abunə olaq. Abunəlik başa çatdıqdan sonra qrupa son məqalənin cari ID-si veriləcək. Gəlin verilənlər bazasına gedək və dəyəri iki məqalə geri dəyişək. Nəticədə, biz lastArticleId-i daha əvvəl təyin etdiyimiz qədər məqalə olacağını gözləyirik . Sonra, sayta daxil oluruq, Java layihələri qrupundakı məqalələri çeşidləyirik - əvvəlcə yeniləri - və siyahıdan üçüncü məqaləyə keçək: Aşağıdakı məqaləyə keçək və ünvan çubuğundan Id - 3313 məqaləsini alırıq: Sonrakı , MySQL Workbench-ə keçin və lastArticleId dəyərini 3313-ə dəyişin. Gəlin görək belə bir qrup verilənlər bazasındadır: Və bunun üçün əmri yerinə yetirəcəyik: Və budur, indi işin növbəti işə salınmasını gözləmək lazımdır. yeni məqalələr axtarın. Java layihələri qrupundan yeni məqalə haqqında iki mesaj alacağımızı gözləyirik. Necə deyərlər, nəticə özünü çox gözlətməyib: Belə çıxır ki, bot gözlədiyimiz kimi işləyir.Son
Həmişə olduğu kimi, biz pom.xml-dəki versiyanı yeniləyirik və RELEASE_NOTES-ə giriş əlavə edirik ki, iş tarixçəsi yadda saxlanılsın və siz həmişə geri qayıdıb nəyin dəyişdiyini başa düşə biləsiniz. Beləliklə, versiyanı bir vahid artırırıq:<version>0.7.0-SNAPSHOT</version>
Və RELEASE_NOTES-i yeniləyin:
GO TO FULL VERSION