JavaRush /Java блогы /Random-KK /Көктемгі жоспарлаушыны қосу - «А-дан Я-ға Java жобасы»
Roman Beekeeper
Деңгей

Көктемгі жоспарлаушыны қосу - «А-дан Я-ға Java жобасы»

Топта жарияланған
Баршаңызға сәлем, қымбатты достарым. Алдыңғы мақалада біз мақалалар үшін JavaRush API-мен жұмыс істеу үшін клиентті дайындадық. Енді біз әр 15 minutes сайын орындалатын жұмысымыздың логикасын жаза аламыз. Дәл осы диаграммада көрсетілгендей: «А-дан Я-ға Java жобасы»: көктемгі жоспарлаушыны қосу - 1әр 15 minutes сайын негізгі қолданбаның фонында орындалатын және келесі әрекеттерді орындайтын жұмыс (біздің ойымызша, белгілі бір сыныптағы әдіс) іске қосылады:
  1. Біздің дерекқордағы барлық топтарда алдыңғы орындалғаннан кейін жарияланған жаңа мақалаларды табады.

    Бұл схема топтардың азырақ санын көрсетеді - тек белсенді пайдаланушылары барлар. Ол кезде бұл маған қисынды болып көрінді, бірақ қазір мен белгілі бір топқа жазылған белсенді пайдаланушылардың бар-жоғына қарамастан, сіз әлі де бот өңдеген соңғы мақаланы жаңартып отыруыңыз керек екенін түсінемін. Жағдай жаңа пайдаланушы осы топты өшіргеннен кейін жарияланған мақалалардың барлық санын бірден алған кезде туындауы мүмкін. Бұл күтпеген әрекет және оны болдырмау үшін қазіргі уақытта белсенді пайдаланушылары жоқ топтарды дерекқорымыздан сақтауымыз керек.
  2. Жаңа мақалалар болса, осы топқа белсенді жазылған барлық пайдаланушылар үшін хабарлар жасаңыз. Егер жаңа мақалалар болмаса, біз жай ғана жұмысты аяқтаймыз.

Айтпақшы, мен TG арнамда бот қазірдің өзінде жұмыс істеп жатқанын және жазылымдарға негізделген жаңа мақалаларды жіберетінін айттым . FindNewArtcileService жазуды бастайық . Хабарламаларды іздеу және жіберу бойынша барлық жұмыс сонда өтеді, ал жұмыс тек осы қызмет әдісін іске қосады:

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();
}
Өте қарапайым, иә? Бұл оның мәні және барлық қиындықтар жүзеге асыруда болады:
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);
   }
}
Мұнда біз бәрін ретімен шешеміз:
  1. groupService көмегімен дерекқордағы барлық топтарды табамыз.

  2. Содан кейін біз барлық топтарға тараймыз және әрқайсысы үшін соңғы мақалада жасалған клиентті шақырамыз - javaRushPostClient.findNewPosts .

  3. Әрі қарай, setNewArticleId әдісін пайдаланып , дерекқорымыз жаңаларын өңдегенімізді білуі үшін соңғы жаңа мақаланың мақала идентификаторын жаңартамыз.

  4. GroupSub-те пайдаланушылар жинағы бар екенін пайдаланып, біз белсенділерді аралап, жаңа мақалалар туралы хабарландырулар жібереміз.

Біз қазір хабардың не екенін талқыламаймыз, бұл біз үшін маңызды емес. Ең бастысы, әдіс жұмыс істейді. Жаңа мақалаларды іздеу және хабарландыруларды жіберу логикасы дайын, сондықтан жұмысты құруға көшуге болады.

FindNewArticleJob жасаңыз

Біз SpringScheduler деген не екенін айтып өттік, бірақ оны тез қайталайық: бұл біз орнатқан белгілі бір уақытта орындалатын фондық процесті құруға арналған Spring шеңберіндегі механизм. Бұл үшін сізге не керек? Бірінші қадам - ​​көктемгі енгізу сыныбына @EnableScheduling annotationсын қосу :
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);
   }

}
Екінші қадам - ​​сыныпты жасау, оны ApplicationContext ішіне қосу және онда мерзімді түрде іске қосылатын әдісті жасау. Біз жұмыс пакетін репозиторий, қызмет және т.б. деңгейінде жасаймыз және FindNewArticleJob сыныбын жасаймыз :
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));
   }
}
Бұл сыныпты қолданба контекстіне қосу үшін мен @Component annotationсын қолдандым . Сынып ішіндегі әдіс оны мерзімді түрде іске қосу қажет екенін білуі үшін мен әдіске annotation қостым: @Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}") . Бірақ біз оны application.properties файлында орнаттық:
bot.recountNewArticleFixedRate = 900000
Мұнда мән миллисекундпен берілген. 15 minutes болады. Бұл әдісте бәрі қарапайым: мен оның қаншалықты жылдам жұмыс істейтінін түсіну үшін жаңа мақалаларды іздеуді есептеу үшін журналдарға өзім үшін өте қарапайым метрика қостым.

Жаңа функцияларды тексеру

Енді біз сынақ ботымызда сынақтан өткіземіз. Бірақ қалай? Хабарландырулар келгенін көрсету үшін мақалаларды әр уақытта жоймаймын ба? Жоқ әрине. Біз жай ғана дерекқордағы деректерді өңдеп, қолданбаны іске қосамыз. Мен оны сынақ serverімде тексеремін. Ол үшін кейбір топқа жазылайық. Жазылым аяқталғаннан кейін топқа соңғы мақаланың ағымдағы идентификаторы беріледі. Дерекқорға өтіп, екі мақаланың мәнін өзгертейік. Нәтижесінде, біз lastArticleId параметрін бұрын орнатқандай көп мақалалар болады деп күтеміз . «А-дан Я-ға Java жобасы»: көктемгі жоспарлаушыны қосу - 2Әрі қарай, біз сайтқа өтіп, Java жобалары тобындағы мақалаларды сұрыптаймыз - алдымен жаңалары - және тізімнен үшінші мақалаға өтіңіз: "Java-проект от А до Я": Добавляем Spring Scheduler - 3Төменгі мақалаға өтейік және мекенжай жолағынан Id - 3313 мақаласын аламыз: "Java-проект от А до Я": Добавляем Spring Scheduler - 4Келесі , MySQL Workbench бөліміне өтіп, lastArticleId мәнін 3313 мәніне өзгертіңіз. Мұндай топтың дерекқорда бар екенін көрейік: "Java-проект от А до Я": Добавляем Spring Scheduler - 5Ал ол үшін пәрменді орындаймыз: "Java-проект от А до Я": Добавляем Spring Scheduler - 6Міне бітті, енді жұмыстың келесі іске қосылуын күту керек. жаңа мақалаларды іздеңіз. Біз Java жобалары тобынан жаңа мақала туралы екі хабарлама аламыз деп күтеміз. Олар айтқандай, нәтиже көп күттірмеді: "Java-проект от А до Я": Добавляем Spring Scheduler - 7бот біз күткендей жұмыс істеді.

Аяқталу

Әдеттегідей, біз pom.xml нұсқасын жаңартамыз және RELEASE_NOTES жазбасына жазба қосамыз, осылайша жұмыс тарихы сақталады және сіз әрқашан оралып, не өзгергенін түсіне аласыз. Сондықтан біз нұсқаны бір бірлікке арттырамыз:
<version>0.7.0-SNAPSHOT</version>
Және RELEASE_NOTES-ті жаңарту:
## 0.7.0-SNAPSHOT * JRTB-4: жаңа мақалалар туралы хабарландырулар жіберу мүмкіндігі қосылған * JRTB-8: белсенді емес телеграм пайдаланушысын орнату мүмкіндігі қосылған * JRTB-9: белсенді пайдаланушыны орнату және/немесе оны пайдалануды бастау мүмкіндігі қосылған.
Енді сіз тарту сұрауын жасай аласыз және жаңа өзгерістерді жүктей аласыз. Мұнда екі бөліктен тұратын барлық өзгерістері бар тарту сұрауы берілген: STEP_8 . Ары қарай не? Барлығы дайын, біз айтқандай, өндіріске кіре алатындай көрінетін, бірақ әлі де істегім келетін нәрселер бар. Мысалы, бот үшін әкімшілердің жұмысын конфигурациялаңыз, оларды қосыңыз және орнату мүмкіндігін қосыңыз. Сондай-ақ, аяқтамас бұрын codeты қарап шығу және қайта өңдеуге болатын нәрселер бар-жоғын көру жақсы идея. Мен мақала/жазба атауында синхронизацияны көре аламын. Соңында біз нені жоспарлағанымызды және не алғанымызды ретроспективалық түрде жасаймыз. Ал сіз болашақта немен айналысқыңыз келеді? Енді мен сіздермен күннің жарығын көре алатын және көретін өте өрескел идеямен бөлісемін: телеграмма ботымен жұмыс істеуге және мақалаларды іздеуге арналған барлық мүмкіндіктерге ие серіппелі стартер жасау. Бұл тәсілді біріздендіруге және оны басқа телеграмма боттары үшін пайдалануға мүмкіндік береді. Бұл бұл жобаны басқалар үшін қолжетімді етеді және көп адамдарға пайдасын тигізеді. Бұл идеялардың бірі. Тағы бір идея - хабарландыруларды әзірлеуге тереңірек бару. Бірақ бұл туралы сәл кейінірек айтатын боламыз. Назарларыңызға рахмет, әдеттегідей: лайк - жазылу - қоңырау , біздің жобаға жұлдызша , мақалаға пікір қалдырыңыз және бағалаңыз! Оқығаныңыз үшін барлығына рахмет.

Сериядағы барлық материалдардың тізімі осы мақаланың басында.

Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION