Laravel background jobs part 2

teroristd

Registered
Епизод 2 :D.

За тези които не са запознати с първа част предоставям резюме.

Имам queue което изпълнява задачи. Използвам delay за да забавя изпълнението на задачите определено време. Независимо от queue-то имам jquery брояч, който използвам да визуализирам времето оставащо до изпълнението на задачите. След като изтече времето с javascript рефрешвам страницата за да се актуализират промените в базата данни.

Тук ще отбележа някои подробности. Инсталирах си PHP-Vars-To-Js-Transformer, който се оказа супер удобен. Подавам в един обект променливи, които после си използвам в javascript без да правя никакви врътки и щуротии :D.

Стигаме до настоящия проблем. Получава се рзлика около секунда и половина между queue-то и jquery брояч-а. Queue-то е по-бавно, и рефреша се изпълнява преди да са се случили промените в базата. За това реших да забавя рефреша чрез setTimeout с две секунди. Всичко е наред ако не се рефрешва ръчно страницата, иначе на всеки рефреш тези две секунди се натрупват по някакъв начин. По принцип съм готов и на различно решение на проблема.

Нека да кажа малко и за времената.
Queue-то приема число(секунди) за delay-а. Например 20 е давадесет секунди.
Докато jquery брояч-а приема дата. Например 2018/05/25 20:10:25.
Накрая setTimeout-а приема число(милисекунди). Например 2000 е две секунди.

Ето и как подавам променливите.
За queue-то просто си взимам левела на сградата от базата и според него сетвам секундите.
За setTimeout-а по същия начин, с тази разлика че неговата променлива я слагам и в javascript обекта.
PHP:
if ($mines_levels[0]['gold_mine'] == 0)
            {
                $this->_num = 5; // За queue-то
                $this->_jsNum = 7000; // За setTimeout-а
            }
За jquery брояч-а е малко по-сложно. Във метода където се извършва ъпдейта на базата, използвам redis за да записвам крайната дата (само когато е натиснат бутона), слад което го подавам на javascript обекта.
PHP:
            $this->_redis->set('endDate', $this->_endDate);
Ето и как стигам до точното число. Няма да обяснявам подробно, от кода се разбира.
PHP:
            date_default_timezone_set('Europe/Sofia');
            $this->_date = strtotime(date('Y-m-d H:i:s')) + $this->_num;
            $this->_endDate = date("Y-m-d H:i:s", $this->_date);
            $this->_goldMineTime = $this->_redis->get('endDate');

Еми това е в общи линии. Ето и javascript-a.
PHP:
// goldMineTime e датата за таймера
$('#clock').countdown(goldMineTime, function (event) {
   var totalHours = event.offset.totalDays * 24 + event.offset.hours;
    $(this).html(event.strftime(totalHours + ' h. %M m. %S s.'));
});

// jsNum е времето за setTimeout-а 
var timeoutHandle = window.setTimeout(location.reload.bind(location), jsNum);
$('div#clock').countdown(goldMineTime).on('stop.countdown', timeoutHandle);
 
1. Не използвай разни библиотеки за разни неща, ако фреймуорка ти предоставя функционалността.
Какво имам предвид. Illuminate\Support\Facades\View фасадата ти предоставя статичен share метод, с който можеш да споделяш променливи във всички вюта.
Като все пак си мисля, че нещата не трябва да стоят по този начин, както си ги направил, но да оставим това сега настрана.

2. По мое мнение, разликата идва заради различното предоставяне на времената. Гледай да ги нормализираш до един вид (unix timestamp - микро секунди).

3. Като стартираш да строиш някоя сграда презареждаш ли страницата?
3.1. Ако да, то използвай self-invoking function, за да стартираш брояча веднага, когато се стигне до него, а не да чака да зареди DOM-а.
Вече чак като зареди DOM-а, можеш да вземеш текущата стойност и да я визуализираш, но стартирането да таймера трябва да стане незабавно.

Моя съвет е, такива процеси да ги стартираш чрез AJAX, за да може да избягваш такива разлики във времето.
 
Revelation каза:
1. Не използвай разни библиотеки за разни неща, ако фреймуорка ти предоставя функционалността.
Какво имам предвид. Illuminate\Support\Facades\View фасадата ти предоставя статичен share метод, с който можеш да споделяш променливи във всички вюта.
Да обаче нe мога да ги ползвам в javascript.

Revelation каза:
2. По мое мнение, разликата идва заради различното предоставяне на времената. Гледай да ги нормализираш до един вид (unix timestamp - микро секунди).

3. Като стартираш да строиш някоя сграда презареждаш ли страницата?
3.1. Ако да, то използвай self-invoking function, за да стартираш брояча веднага, когато се стигне до него, а не да чака да зареди DOM-а.
Вече чак като зареди DOM-а, можеш да вземеш текущата стойност и да я визуализираш, но стартирането да таймера трябва да стане незабавно.

Моя съвет е, такива процеси да ги стартираш чрез AJAX, за да може да избягваш такива разлики във времето.

Тука в случая се бави queue-то, а не jquery таймера.
 
Не ги ползваш правилно, за това. :D Няма значение, сега не е важна архитектурата.

Т.е. искаш да кажеш, че таймера свършва, презарежда, но Queue-то не е приключило и де факто няма ъпдейт?
 
А винаги ли е еднакво времето - 1.5сек.? Ако е винаги, countdown-а би трябвало да има onComplete event, в който трябва да изпълниш редиректа със setTimeout 1500ms.


П.П. Нещо не разбирам защо имаш 2 countdown-а. И в първия какво е това време и какви са тези bind-ове по setTimeout. Излишна логика виждам тука.

Разясни малко с коментари по кода.
 
Revelation каза:
А винаги ли е еднакво времето - 1.5сек.? Ако е винаги, countdown-а би трябвало да има onComplete event, в който трябва да изпълниш редиректа със setTimeout 1500ms.


П.П. Нещо не разбирам защо имаш 2 countdown-а. И в първия какво е това време и какви са тези bind-ове по setTimeout. Излишна логика виждам тука.

Разясни малко с коментари по кода.

Знаеш че javascripta не ми е сила :D. В случая нещо не можах да ги обединя onComplete-а с таймера, но и така работи. За bind-а го видях в stackoverflow и не знам какво точно се случва но без него(как да го кажа) върти иконката за рефреш на браузъра :D. Всичко работи, но единствения проблем е че ако докато върви countdown-а, ръчно рефрешвам страницата в setTimeout-а се натрупва време. Ако не пипам нищо две секунди след спирането на countdown-а си се рефрешва страницата и всичко е ок. Ако обаче примерно рефрешна переди това един път после чакам четири секунди и т.н.
PHP:
// Това е същинският countdown който визуализирам
$('#clock').countdown(goldMineTime, function (event) {
   var totalHours = event.offset.totalDays * 24 + event.offset.hours;
    $(this).html(event.strftime(totalHours + ' h. %M m. %S s.'));
});

// Това е onComplete event-а
var timeoutHandle = window.setTimeout(location.reload.bind(location), jsNum);
$('div#clock').countdown(goldMineTime).on('stop.countdown', timeoutHandle);
 
Ти яко мажеш нещата. :D :D Не се прави така.


[js]
$('#clock').countdown(goldMineTime)
.on('update.countdown', function (e) {
let totalHours = event.offset.totalDays * 24 + event.offset.hours;
$(this).html(event.strftime(totalHours + ' h. %M m. %S s.'));
})
.on('finish.countdown', function (e) {
setTimeout(function () {
window.location.reload();
}, 1500);
});
[/js]

Това totalHours нямам идея защо ти е. %-H би трябвало да ти свърши работа.
 
Revelation каза:
Ти яко мажеш нещата. :D :D Не се прави така.


[js]
$('#clock').countdown(goldMineTime)
.on('update.countdown', function (e) {
let totalHours = event.offset.totalDays * 24 + event.offset.hours;
$(this).html(event.strftime(totalHours + ' h. %M m. %S s.'));
})
.on('finish.countdown', function (e) {
setTimeout(function () {
window.location.reload();
}, 1500);
});
[/js]

Това totalHours нямам идея защо ти е. %-H би трябвало да ти свърши работа.

Така не работи, не знам защо. totalHours е за да показва часове когато са повече от 24, а не дни. Така си е в примера и аз така искам :) .

Edit

Оправих го, трябвало е вместо function (e) да е event.

Благодаря.
 
teroristd каза:
Revelation каза:
Ти яко мажеш нещата. :D :D Не се прави така.


[js]
$('#clock').countdown(goldMineTime)
.on('update.countdown', function (e) {
let totalHours = event.offset.totalDays * 24 + event.offset.hours;
$(this).html(event.strftime(totalHours + ' h. %M m. %S s.'));
})
.on('finish.countdown', function (e) {
setTimeout(function () {
window.location.reload();
}, 1500);
});
[/js]

Това totalHours нямам идея защо ти е. %-H би трябвало да ти свърши работа.

Така не работи, не знам защо. totalHours е за да показва часове когато са повече от 24, а не дни. Така си е в примера и аз така искам :) .

Edit

Оправих го, трябвало е вместо function (e) да е event.

Благодаря.

О, недогледал съм като съм писал кода. А иначе за часовете %H или %-H не ти ли вършат работа?

И оправи ли се проблема ти?
 
Revelation каза:
teroristd каза:
Revelation каза:
Ти яко мажеш нещата. :D :D Не се прави така.


[js]
$('#clock').countdown(goldMineTime)
.on('update.countdown', function (e) {
let totalHours = event.offset.totalDays * 24 + event.offset.hours;
$(this).html(event.strftime(totalHours + ' h. %M m. %S s.'));
})
.on('finish.countdown', function (e) {
setTimeout(function () {
window.location.reload();
}, 1500);
});
[/js]

Това totalHours нямам идея защо ти е. %-H би трябвало да ти свърши работа.

Така не работи, не знам защо. totalHours е за да показва часове когато са повече от 24, а не дни. Така си е в примера и аз така искам :) .

Edit

Оправих го, трябвало е вместо function (e) да е event.

Благодаря.

О, недогледал съм като съм писал кода. А иначе за часовете %H или %-H не ти ли вършат работа?

И оправи ли се проблема ти?

Да проблема е решен. А иначе за часовете %H или %-H не ми вършат работа, защото за по-голямо време от 24 часа ми трябва и поле за дни, а аз не искам. Така както е ще показва сбора от часовете.
 

Горе