JavaRush /جاوا بلاگ /Random-UR /اسپرنگ شیڈولر کو شامل کرنا - "A سے Z تک جاوا پروجیکٹ"

اسپرنگ شیڈولر کو شامل کرنا - "A سے Z تک جاوا پروجیکٹ"

گروپ میں شائع ہوا۔
سب کو سلام، میرے پیارے دوستو۔ پچھلے مضمون میں ، ہم نے مضامین کے لیے JavaRush API کے ساتھ کام کرنے کے لیے ایک کلائنٹ تیار کیا تھا۔ اب ہم اپنے کام کے لیے منطق لکھ سکتے ہیں، جو ہر 15 منٹ بعد عمل میں آئے گی۔ بالکل جیسا کہ اس خاکہ میں دکھایا گیا ہے: "A سے Z تک جاوا پروجیکٹ": اسپرنگ شیڈیولر کو شامل کرنا - 1ہر 15 منٹ میں ایک کام شروع کیا جائے گا (ہماری رائے میں، ایک مخصوص کلاس میں صرف ایک طریقہ)، جو کہ مرکزی درخواست کے پس منظر میں عمل میں لایا جاتا ہے اور درج ذیل کام کرتا ہے:
  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. گروپ سروس کا استعمال کرتے ہوئے ہم ڈیٹا بیس میں موجود تمام گروپس کو تلاش کرتے ہیں۔

  2. پھر ہم تمام گروپس میں منتشر ہو جاتے ہیں اور ہر ایک کے لیے ہم آخری مضمون میں تخلیق کردہ کلائنٹ کو کال کرتے ہیں - javaRushPostClient.findNewPosts ۔

  3. اس کے بعد، setNewArticleId طریقہ استعمال کرتے ہوئے ، ہم اپنے تازہ ترین نئے مضمون کی مضمون ID کو اپ ڈیٹ کرتے ہیں تاکہ ہمارے ڈیٹا بیس کو معلوم ہو کہ ہم نے پہلے ہی نئے پر کارروائی کر لی ہے۔

  4. اور اس حقیقت کو استعمال کرتے ہوئے کہ GroupSub کے پاس صارفین کا مجموعہ ہے، ہم فعال صارفین سے گزرتے ہیں اور نئے مضامین کے بارے میں اطلاعات بھیجتے ہیں۔

اب ہم اس بات پر بحث نہیں کریں گے کہ پیغام کیا ہے، یہ ہمارے لیے بہت اہم نہیں ہے۔ اہم بات یہ ہے کہ طریقہ کار کام کرتا ہے۔ نئے مضامین تلاش کرنے اور اطلاعات بھیجنے کی منطق تیار ہے، لہذا آپ نوکری پیدا کرنے کے لیے آگے بڑھ سکتے ہیں۔

FindNewArticleJob بنائیں

ہم پہلے ہی اس کے بارے میں بات کر چکے ہیں کہ اسپرنگ شیڈیولر کیا ہے، لیکن آئیے اسے جلدی سے دہراتے ہیں: یہ پس منظر کے عمل کو بنانے کے لیے بہار کے فریم ورک میں ایک طریقہ کار ہے جو ہمارے مقرر کردہ مخصوص وقت پر چلے گا۔ آپ کو اس کے لیے کیا چاہیے؟ پہلا قدم ہماری بہار ان پٹ کلاس میں @EnableScheduling تشریح شامل کرنا ہے۔
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 تشریح کا استعمال کیا ۔ اور اس لیے کہ کلاس کے اندر کا طریقہ جانتا ہے کہ اسے وقتاً فوقتاً چلانے کی ضرورت ہے، میں نے طریقہ کار میں ایک تشریح شامل کی: @Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}") ۔ لیکن ہم نے اسے application.properties فائل میں سیٹ کیا ہے۔
bot.recountNewArticleFixedRate = 900000
یہاں قدر ملی سیکنڈ میں ہے۔ 15 منٹ ہوں گے۔ اس طریقے میں، سب کچھ آسان ہے: میں نے نئے مضامین کی تلاش کا حساب لگانے کے لیے لاگز میں اپنے لیے ایک انتہائی سادہ میٹرک شامل کیا، تاکہ کم از کم یہ سمجھ سکیں کہ یہ کتنی تیزی سے کام کرتا ہے۔

نئی فعالیت کی جانچ

اب ہم اپنے ٹیسٹ بوٹ پر ٹیسٹ کریں گے۔ لیکن کس طرح؟ میں ہر بار یہ ظاہر کرنے کے لیے مضامین کو حذف نہیں کروں گا کہ اطلاعات آچکی ہیں؟ ہرگز نہیں۔ ہم صرف ڈیٹا بیس میں ڈیٹا میں ترمیم کریں گے اور ایپلیکیشن لانچ کریں گے۔ میں اسے اپنے ٹیسٹ سرور پر آزماؤں گا۔ ایسا کرنے کے لیے، آئیے کسی گروپ کو سبسکرائب کریں۔ سبسکرپشن مکمل ہونے پر، گروپ کو تازہ ترین مضمون کی موجودہ ID دی جائے گی۔ آئیے ڈیٹا بیس پر جائیں اور قدر دو آرٹیکلز کو واپس تبدیل کریں۔ نتیجے کے طور پر، ہم توقع کرتے ہیں کہ اتنے ہی مضامین ہوں گے جتنے کہ ہم نے lastArticleId کو پہلے سیٹ کیا تھا ۔ "A سے Z تک جاوا پروجیکٹ": اسپرنگ شیڈیولر کو شامل کرنا - 2اس کے بعد، ہم سائٹ پر جاتے ہیں، جاوا پروجیکٹس گروپ میں مضامین کو ترتیب دیتے ہیں - پہلے نئے - اور فہرست سے تیسرے مضمون پر جائیں: "Java-проект от А до Я": Добавляем Spring Scheduler - 3آئیے نیچے والے مضمون پر جائیں اور ایڈریس بار سے ہمیں آرٹیکل آئی ڈی - 3313: "Java-проект от А до Я": Добавляем Spring Scheduler - 4اگلا ملتا ہے۔ ، MySQL Workbench پر جائیں اور lastArticleId ویلیو کو 3313 میں تبدیل کریں۔ آئیے دیکھتے ہیں کہ ایسا گروپ ڈیٹا بیس میں ہے: "Java-проект от А до Я": Добавляем Spring Scheduler - 5اور اس کے لیے ہم کمانڈ پر عمل کریں گے: "Java-проект от А до Я": Добавляем Spring Scheduler - 6اور بس، اب آپ کو جاب کے اگلے آغاز تک انتظار کرنا ہوگا۔ نئے مضامین تلاش کریں۔ ہمیں جاوا پروجیکٹس گروپ سے ایک نئے مضمون کے بارے میں دو پیغامات موصول ہونے کی توقع ہے۔ جیسا کہ وہ کہتے ہیں، نتیجہ آنے میں زیادہ دیر نہیں تھی: "Java-проект от А до Я": Добавляем Spring Scheduler - 7یہ پتہ چلتا ہے کہ بوٹ نے ہماری توقع کے مطابق کام کیا۔

ختم ہونے والا

ہمیشہ کی طرح، ہم ورژن کو pom.xml میں اپ ڈیٹ کرتے ہیں اور RELEASE_NOTES میں ایک اندراج شامل کرتے ہیں تاکہ کام کی تاریخ محفوظ ہو جائے اور آپ ہمیشہ واپس جا کر سمجھ سکیں کہ کیا تبدیلی آئی ہے۔ لہذا، ہم ورژن کو ایک یونٹ سے بڑھاتے ہیں:
<version>0.7.0-SNAPSHOT</version>
اور RELEASE_NOTES کو اپ ڈیٹ کریں:
## 0.7.0-اسنیپ شاٹ * JRTB-4: نئے مضامین کے بارے میں اطلاعات بھیجنے کی اضافی صلاحیت * JRTB-8: غیر فعال ٹیلیگرام صارف کو سیٹ کرنے کی اضافی صلاحیت * JRTB-9: فعال صارف کو سیٹ کرنے اور/یا اسے استعمال کرنا شروع کرنے کی صلاحیت میں اضافہ۔
اب آپ پل کی درخواست بنا سکتے ہیں اور نئی تبدیلیاں اپ لوڈ کر سکتے ہیں۔ دو حصوں میں تمام تبدیلیوں کے ساتھ پل کی درخواست یہ ہے: STEP_8 ۔ اس کے بعد کیا ہے؟ ایسا لگتا ہے کہ سب کچھ تیار ہے اور، جیسا کہ ہم کہتے ہیں، یہ پیداوار میں جا سکتا ہے، لیکن اب بھی کچھ چیزیں ہیں جو میں کرنا چاہتا ہوں. مثال کے طور پر، بوٹ کے لیے ایڈمنز کے کام کو ترتیب دیں، انہیں شامل کریں اور انہیں سیٹ کرنے کی صلاحیت شامل کریں۔ یہ بھی ایک اچھا خیال ہے کہ کوڈ کو ختم کرنے سے پہلے دیکھیں اور دیکھیں کہ کیا ایسی چیزیں ہیں جن کو دوبارہ بنایا جا سکتا ہے۔ میں آرٹیکل/پوسٹ کے نام میں پہلے سے ہی غیر مطابقت پذیری دیکھ سکتا ہوں۔ بالکل آخر میں، ہم اس بات کا جائزہ لیں گے کہ ہم نے کیا منصوبہ بنایا اور ہمیں کیا ملا۔ اور آپ مستقبل میں کیا کرنا چاہیں گے؟ اب میں آپ کے ساتھ ایک بہت ہی خام خیال کا اشتراک کروں گا جو دن کی روشنی کو دیکھ سکتا ہے اور دیکھ سکتا ہے: ایک اسپرنگ بوٹ اسٹارٹر بنانا جس میں ٹیلیگرام بوٹ کے ساتھ کام کرنے اور مضامین کی تلاش کے لیے تمام فعالیت موجود ہوں۔ اس سے نقطہ نظر کو یکجا کرنا اور دوسرے ٹیلیگرام بوٹس کے لیے استعمال کرنا ممکن ہو جائے گا۔ اس سے یہ پروجیکٹ دوسروں کے لیے زیادہ قابل رسائی ہو جائے گا اور زیادہ سے زیادہ لوگ مستفید ہو سکتے ہیں۔ یہ خیالات میں سے ایک ہے۔ ایک اور خیال نوٹیفکیشن کی ترقی میں گہرائی میں جانا ہے۔ لیکن ہم اس پر تھوڑی دیر بعد بات کریں گے۔ آپ کی توجہ کے لیے آپ سب کا شکریہ، ہمیشہ کی طرح: پسند کریں - سبسکرائب کریں - گھنٹی ، ہمارے پروجیکٹ کے لیے ستارہ ، تبصرہ کریں اور مضمون کی درجہ بندی کریں! پڑھنے کے لیے سب کا شکریہ۔

سیریز کے تمام مواد کی فہرست اس مضمون کے شروع میں ہے۔

تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION