Laravel background jobs

C++ JAVA
Post Reply
User avatar
teroristd
Много Редовен
Много Редовен
Posts: 1769
Joined: Thu Feb 18, 2010 11:50 am
Answers: 83

Post by teroristd » Fri Apr 27, 2018 12:43 pm

Значи Queue-то се изпълнява но само един път защото е извън Scheduler-а.

User avatar
Revelation
Потребител
Потребител
Posts: 776
Joined: Sun Mar 24, 2013 1:23 pm
Answers: 57

Post by Revelation » Fri Apr 27, 2018 12:52 pm

Ти не ти трябва Scheduler-а за тази цел. Просто му задай delay(now()->addMinutes(time)) като time е времето, за което трябва да се построи сградата.

А иначе, за да работи правилно queue, трябва да си направиш таблица в базата данни:

[php]
php artisan queue:table
php artisan migrate
php artisan queue:work
[/php]

иначе дори и да сложиш delay няма да работи правилно и ще вика веднага dispatch().

User avatar
teroristd
Много Редовен
Много Редовен
Posts: 1769
Joined: Thu Feb 18, 2010 11:50 am
Answers: 83

Post by teroristd » Fri Apr 27, 2018 1:09 pm

Аз съм му направил таблицата, но тука проблема е че когато е извън sceduler-a трябва да му подам командата ръчно. Разбираш ли ме какво имам на предвид?

За да го обясня по цветно, в началото като стартирам scheduler-a почва да се трупа злато през една минута, но камъните си стоят нула. Целта е когато играча построи мината да се стартира втората задача и да почнат да се трупат и камъни, но това не се случва защото queue-to е извън цикъла.

User avatar
Revelation
Потребител
Потребител
Posts: 776
Joined: Sun Mar 24, 2013 1:23 pm
Answers: 57

Post by Revelation » Fri Apr 27, 2018 1:43 pm

Ще опитам да ти разясня отново стъпка по стъпка:

0. Тази задача не трябва да участва в scheduler-а. За да се изпълняват queue работите, трябва да имаш стартиран php artisan queue:work

1. Queue работата(ще я кръстя UpdateResourcesPerMinJob) има за цел да ти вземе данните(взети и подадени от контролера), да речем user_id и името на сградата - да речем gold(това ще е името и на полето ти в базата данни, което ще трябва да се ъпдейтне), както също и данни като например след като се построи сградата с колко трябва да увеличиш полето gold.

2. Правиш си контролер, на който работата му ще е да строи сгради. В него идеята е да извикаш UpdateResourcesPerMinJob и да го dispatch()-неш като на dispatch() подаваш нужните данни(user_id, building name и т.н., като ти препоръчвам building да е обект, с който да можеш да работиш в самото queue) + му закачаш един delay(), който ще е времето, което ще е нужно да се построи сградата. Така, когато натиснеш бутона за построяване, де факто dispatch()-ваш опашката. По-лесно казано, регистрираш я в базата данни и queue:work вече ще знае кога тази опашка трябва да се извика и да се изпълни.
И вече, да речем, ако на сградата са и били нужни 5мин. да се построи, след тези 5мин. опашката ще се изпълни, ще ти ъпдейтне таблицата resources_per_min за съответната колона(име на сграда) и оттам вече, теб не те интересува scheduler-а какво върши, защото той си изпълнява неговата работа да вика командата, която ъпдейтва ресурсите на потребитела. Съответно, след като се ъпдейтне таблица след построяването на сградата, при следващия тик на scheduler-а, той просто ще си вземе новите данни от базата данни ще ъпдейтва според това, какво има там.


Аз май няколко точки ги обясних в т.2, но са просто навързани.

Надявам се, че започваш да разбираш за какво говоря. Ако не, ще видя, ако ми остане някакво време да ти го реализирам, но ти препоръчвам да се справиш сам, за да разбереш процеса на работа.

User avatar
teroristd
Много Редовен
Много Редовен
Posts: 1769
Joined: Thu Feb 18, 2010 11:50 am
Answers: 83

Post by teroristd » Fri Apr 27, 2018 2:49 pm

Revelation wrote:Надявам се, че започваш да разбираш за какво говоря. Ако не, ще видя, ако ми остане някакво време да ти го реализирам, но ти препоръчвам да се справиш сам, за да разбереш процеса на работа.
Аз искам сам да си го направя. В крайна сметка целта е да се науча. Нещо не мога да схвана логиката. Значи ако разбирам правилно sheduler-a само следи дали има построена дадената мина. Ако няма не ъпдейтва. На queue-тата работата им е да строят сгради.

Само че тука виждам един проблем. Поправи ме ако греша.
Да кажем стартирам php artisan queue:work но в момента в който затворя конзолата той спира да работи. Така ли е?

User avatar
anonimen
Много Редовен
Много Редовен
Posts: 1523
Joined: Mon Jun 11, 2012 6:07 pm
Answers: 162
Location: Parse error: unexpected "}" in /home/index.php on line 26

Post by anonimen » Fri Apr 27, 2018 3:00 pm

Да кажем стартирам php artisan queue:work но в момента в който затворя конзолата той спира да работи. Така ли е?
Да, защото конзолата е parent process на стартираната php команда. Виж как в уиндоус да стартираш background process.

П.п. ето ти: https://superuser.com/questions/198525/ ... background
START /B program

User avatar
Revelation
Потребител
Потребител
Posts: 776
Joined: Sun Mar 24, 2013 1:23 pm
Answers: 57

Post by Revelation » Fri Apr 27, 2018 3:35 pm

Пак стъпка по стъпка:

Scheduled Tasks
1. Scheduler-а се интересува да има направена команда update:resources
2. Командата се интересува да има създадена таблица resources_per_min

Процес на работа:
1. Schduler-а се изпълнява всяка минута, проверява дали има задачи за изпълнение и ако има ги изпълнява. В случая ти имаш.
2. Командата се изпълнява, взима текущите данни от resources_per_min и ъпдейтва съответно стойностите в resources. Край.
3. Връщаме се на т1.

Добавка: Scheduler-а винаги се изпълнява щом му дойде времето(в твоя случай всяка минута). В твоя случай, той не следи дали има построена дадена мина. Него го интересува само данните да са налични, за да не праска грешки. Дали всички стойности ще са 0, не го интересува, той ще си се изпълнява.

Важно: Тази команда има за задача да ъпдейтва на всички потребители ресурсите. За тази цел в командата трябва да завърташ цикъл с всички потребители.

Queue Jobs обяснени за твоята задача
1. Queue Jobs(в твоя случай UpdateResourcesPerMinJob) се интересува от данните на потребителя и данните на сградата, която строиш.
1.1. Данните на потребителя ти трябват, за да знаеш на кой точно потребител трябва да ъпдейтнеш данните в resources_per_min
1.2. Данните за сградата ти трябват, за да знаеш коя колона да промениш. Ако строиш каменна мина, да промениш стойността на кеманната мина. Съответно и за другите.
Съвет: Изпращай обект Building(за пример), от който ще можеш да взимаш името на сградата, нивото, ресурсите след всяко ниво, които трябва да получаваш(това е най-важно всъщност) и т.н.
2. Да имаш queue worker пуснат.
Информация: Да, винаги трябва да е отворена или както ти казаха, да пуснеш процеса в бекграунд. Но това са подробности, които не ти трябват, ако го правиш само с научна цел.

Процес на работа
1. Имаш контролер, който управлява строенето на всички сгради.
1.1. Контролера не се интересува каква ще е сградата, стига да е сграда.
2. При извикване на съответния метод, който в случая се вика при кликане на бутон за строене на сграда, има за цел да регистрира задачата - UpdateResourcesPerMinJob::dispatch(array params)
3. Ако не зададеш delay, то задачата ще се изпълни веднага, но ни не искаме това.
4. Закачаш на dispatch() един delay(), който трябва да е времето за строене на сградата, за да може чак след като строежа приключи, задачата да се изпълни.
5. Сградата е построена, изпълнява се задачата, ъпдейтва resources_per_min и приключва.

Информация: Задачата трябва да се регистрира само и единствено, когато е натиснат бутон за строене на сграда или респективно, когато се извика съответния action в контролера, И трябва да се изпълнява винаги след като сградата се построи или иначе казано със закъснение(delay)

Надявам се вече да е малко по-ясно какво се случва, че се уморих. :D

User avatar
teroristd
Много Редовен
Много Редовен
Posts: 1769
Joined: Thu Feb 18, 2010 11:50 am
Answers: 83

Post by teroristd » Fri Apr 27, 2018 4:25 pm

Руска печка съм знам :D, ама какво да правя. Мисля че разбрах от къде идва объркването ми. В графиката която ми даде в началото двете таблици са с абсолютно еднакви имена на колоните. Да вземем за пример полето gold. Какво се очаква да съдържа в едната и в другата таблица? Името на мината или там се трупа златото?

User avatar
Revelation
Потребител
Потребител
Posts: 776
Joined: Sun Mar 24, 2013 1:23 pm
Answers: 57

Post by Revelation » Fri Apr 27, 2018 5:01 pm

resources - съдържа събраните от потребителя ресурси
[sql]
user_id
total_gold
total_iron
total_stone
[/sql]

Пример:
Потребителя в момента има:
* Злато - 1500
* Желязо - 300
* Камък - 765
________________________________________

resources_per_min - съдържа по колко ресурси да събира на минута(ако искаш ги пази и на час, просто ще трябва да делиш на 60)
[sql]
user_id
gold_per_min
iron_per_min
stone_per_min
[/sql]

Пример:
Потребителя на час трябва да прави:
* Злато - 840 (или по 14 на минута)
* Желязо - 180 (или по 3 на минута)
* Камък - 540 (или по 9 на минута)
________________________________________

Процес на минута: (работа на scheduler-a)
Тик 1:
* Злато = 1500 + 14 = 1514
* Желязо = 300 + 3 = 303
* Камък = 765 + 9 = 774

Тик 2:
* Злато = 1514 + 14 = 1528
* Желязо = 303 + 3 = 306
* Камък = 774 + 9 = 783

... продължава надолу ...
________________________________________

Строеж на желязна мина за потребител Х:
1. Взимаме ресурси за построяването
* Злато = 1528 - 180 = 1348
* Желязо = 306 - 30 = 276
* Камък = 783 - 83 = 700

2. Регистрира се задача, която трябва да се изпълни след 10 минути
3. След 10 минути се изпълнява задачата
4. Желязната мина вече трябва да дава по 300 на час(5 на мин)
5. Ъпдейт на resources_per_min
* Злато - 840 (14 на мин) - не се променя
* Желязо - (стари 180 (3 на мин) ) - 300 (5 на мин) - само тази колона променяме от UpdateResourcesPerMinJob
* Камък - 540 (9 на мин) - не се променя
_________________________________________

след 10 минути (предполагаемото време за построяването на новата сграда) ресурсите са следните:

* Злато = 1348 + (14з./мин * 10 мин) = 1488
* Желязо = 276 + (3ж./мин * 10 мин) = 306
* Камък = 700 + (9к./мин * 10 мин) = 790
(Тези са се обновявали през това време от scheduler-a)

От тука вече имаме построена сграда и нова стойност за добива на желязо
... Тик 13:
* Злато = 1488 + 14 = 1502
* Желязо = 306 + 5 = 311
* Камък = 790 + 9 = 799

Тик 14:
* Злато = 1502 + 14 = 1516
* Желязо = 311 + 5 = 316
* Камък = 799 + 9 = 808

И т.н.


Баси, трябва да напиша статия. Аз колкото неща описах тука и както ги описах трябва да си търся и авторско право, хаха. :D

User avatar
teroristd
Много Редовен
Много Редовен
Posts: 1769
Joined: Thu Feb 18, 2010 11:50 am
Answers: 83

Post by teroristd » Fri Apr 27, 2018 5:13 pm

Ще ти дам да поиграеш безплатно :D.

Post Reply