Laravel Türkiye Discord Kanalı Forumda kod paylaşılırken dikkat edilmesi gerekenler!Birlikte proje geliştirmek ister misiniz?

Merhaba herkese,

Local olarak calistirdigim projede cron job nasil calistira bilirim. Her seyi uyguladim schedule run yapinca sadece 1 kez calisiyor everyminute olmasina ragmen 1 kez calisiyor 1 dakika sonra yeniden calismiyor her defa command calistirmak zorunda kaliyorum. Nasil yapa bilirim?

  • sineld Ben en iyisi sizi boşa uğraştırmayayım direkt istediğiniz cevabı vereyim: Her bir URL'deki veriyi çekip kaydeden işi kuyruğa atacaksınız, arkada çekip kaydedecek.

    ScrapUrl::dispatch("http://site.com/?page=1")
    ScrapUrl::dispatch("http://site.com/?page=2")
    ScrapUrl::dispatch("http://site2.com/?page=1")
    ...

Laravel 8 yayınlandıktan kısa bir süre sonra gelen bir özellik tam istediğinizi yapıyor:

php artisan queue:work

Her dakika çalışan bir cron izleyici.

    sineld Eyvallah hocam tesekkurler. Localde ve Productionda calisiyormu? yani server tarafta ekstra bir islem yapmadan.

      CodeWriteson Sunucuda normal cron kullanmanız gerekiyor, bu komut sadece geliştirme ortamı için.

        mgsmus Hocam sizi bulmusken bir sorum vardi)) Queue jobs kullanim alani olarak en cok hangi islemlerde yaygin kullanilir yani ne zaman burda queue jobs kullanmam lazim denir.

          CodeWriteson Bir istekte yaptığınız işlemler bir sonrakini bloke edecek şekilde çalışır, yani tamamlanmadan diğer işleme geçmez. Bu işlemlerden bazıları aynı istekte olmak zorunda değildir, örneğin mail gönderme gibi. Bir sipariş kaydı oluşturunca sonrasında kullanıcı mail gitsin diye beklemek zorunda değil çünkü "siparişiniz alındı" maili siparişin oluşması için bir gereksinim değil. Bunu arka planda gönderebilirsiniz ve böylece kullanıcı deneyimi daha yumuşak olur.

          Bazı işlemler uzun sürebilir örneğin kayıtların Excel'e aktarılması, yıllık raporların oluşturulması ya da video render edilmesi gibi. Bu işlemler de arka planda yaptırılabilir. Kullanıcı sadece işlemi başlatır, bittiğinde dosyayı mail ile göndereceğiz gibi bir mesajla bilgilendirilir, uygulamayı kullanmaya devam eder. İşlem arka planda çalışır, kullanıcıyı bekletmez.

          Günlük rutin, periyodik işler arka planda yaptırılabilir. 3. parti servislerden bilgi çekmek, güncellemek, sistem taraması yapmak vs gibi. Bunlar cron ile yapılıyor fakat bazen istek sınırlamaları oluyor. Mesela elinizdeki kayıtları karşı tarafa iletip bazı verileri alacaksınız ya da elinizdekileri güncelleyeceksiniz. Tek seferde 100 tane yapabiliyorsunuz, limit var, ama sizde 1000 kayıt var. Cron ile çalışan zamanlanmış görev kayıtlardan 100'er tane çekip (chunk kullanarak mesela) güncellemeyi yapan bir Job'ı bu 100 kayıtla kuyruğa atar, toplamda 10 tane Job (1000 / 100 = 10) kuyrukta sıraya girer, hepsi sırayla çalışır. Bu şekilde limit problemlerini çözmenizi sağlayabilir.

          Bazen bazı işlemleri paralel gerçekleştirmek istersiniz, bu size zamandan tasarruf sağlar, bunun için birden fazla kuyruk kullanabilirsiniz. Örneğin 1000 kaydı işlemek 1000 dk sürüyorsa bunları 100'erli gruplar halinde aynı anda 10 farklı kuyruğa attığınızda 100 dk sürer.

          Bazı işlemler ilk seferinde başarılı olmaz, örneğin kullandığınız 3. parti servise anlık erişemeyebilirsiniz. Kuyruğa atılan işler tekrarlanabilir olduğu için bu tür işleri kuyrukta halletmek bu sorunu ortadan kaldırır. Örneğin iş, 3. denemesinde başarılı olur.

          Başka kullanım alanları da vardır ama genellikle hep benzer noktalarda buluşuyorlar o yüzden genel olarak bunlar.

            mgsmus Ancak bu kadar guzel anlatila bilirdi elinize saglik. O zaman soyle soyleleyim size gecen sefer anlattigim siteden veri cekme mesela. Benden 1000 sayfadan veri cekmem isteniyor. pagination var. O zaman Her page icin job yaratmam ve onu kuyrukla arka planda calistirmam gerek oyle degilmi? kullanicidida arkadan giden isdden haberi olmaz. Ve Crona bagli her 1 saatda bir request aticak , o zaman fazla bilgi icin job olusturucam oylemi? SAdece tek anlamadigm job un bir tanesi 1 sayfadan veri cekicekse diger joblari mesele 100 tane job lazim kuyrukta ayni isi gorucek dinamik olarak create yapmak mumkunmu? kendisi mesele 10000 veriyi 100 job olarak queue da isletsin.

              CodeWriteson

              $lastPage = 120; // Bunu önce çekeceksiniz. Çektiniz, 120 geldi.
              
              for($i = 0; $i < $lastPage; $i++) {
                  ScrapUrl::dispatch(
                      sprintf("https://www.site.com/haberler?page=%d", $i)
                  );
              }

              Bu yani kabaca yapacağınız.

              Daha önce de dediğim gibi sayfa no olmayan, arkada yapan, ajax kullanan vs siteler için strateji belirleyip nasıl sayfaladığını kayıtları getirdiğini bulup ona göre işlem yapacaksınız.

              Eyvallah. o zaman ben en iyisi scrapper manager i sizin onerdiginiz ScrapperMAnager - command icinde degilde job olusturarak onun icinde cagirayim .dogru anladim umarim. Bundan once ScrapperCommand olsuturmustum

              public function handle()
              {
              $scrapper = new ScrapperManager([
              Service1::class => 'url1l',
              Service2::class => 'url2r',
              ]);

                  foreach($scrapper->scrap() as $data) {
                      // data --> ScrappedData olacaq.
                      News::firstOrCreate([
                          'site_name' => $data->getSiteName(),
                          'title' => $data->getTitle(),
                      ], [
                          'link' => $data->getLink(),
                          'img' => $data->getImage()
                      ]);
                  }
              
                  $this->info('Successfully scrapped');
              }

              sondada schedule:work yaparak calistiriyordum . commandi job a degistirecem o zaman oylemi?

                CodeWriteson Command kalacak, datayı çeken kısmı Job yapacaksınız. Komutu işleri kuyruğa atmak için kullanacaksınız. Yani ScrapperCommand her bir link için kuyruğa Job atmakla yükümlü olacak.

                  mgsmus Hocam o zaman commandda yaptigim data cekmeyi job a aktaricam. Amma mesela her service de kendi icerisinda buyuk veriler return yapiyor. Ve en onda scrapper manager ile verilen toplaniyor bir yerde. O kisim icin job falan gerekli degilmi mesela her service icin. Sonucta veriler servislerden gelip toplaniyor ayni veri zaten toplaniyor ve en sonda isleniyor. Sadece command kisimdaki veri islemeyi job yaparsak yetecekmi?

                  mgsmus Hocam birde son olarak queue_connection sync mi olacak yoksa database mi? bu durumlarda hangiisi onerilir?

                    sineld Ben en iyisi sizi boşa uğraştırmayayım direkt istediğiniz cevabı vereyim: Her bir URL'deki veriyi çekip kaydeden işi kuyruğa atacaksınız, arkada çekip kaydedecek.

                    ScrapUrl::dispatch("http://site.com/?page=1")
                    ScrapUrl::dispatch("http://site.com/?page=2")
                    ScrapUrl::dispatch("http://site2.com/?page=1")
                    ...

                      CodeWriteson Ben Redis kullanıyorum, memnunum. Sync demek kuyruk yok, direkt ateşle demek 🙂 Redis imkanı varken database tavsiye etmiyorum.

                        mgsmus Redis olurken local de ve sunucuda ayri ayri kurulummu yapmam gerecek?