Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: dynamiczny cron
Forum PHP.pl > Forum > PHP
nospor
Potrzebuję mieć dynamiczny cron, tzn. użytkownicy aplikacji mogą tworzyć różne zdarzenia i chcieć je wywoływać o określonej porze.
Rozważam dwa rozwiązania:
1) Aplikacja dodaje wpisy do crona
2) Dane czasowe zapisuję w bazie i w cronie co minutę latam po bazie i sprawdzam czy akurat teraz jest jakiś zaplanowany wpis

Problemy dla rozwiązania 1):
- z czasem zdarzeń może być tysiące. Czy nie zapełni mi się cron przy takiej liczbie wpisów?
- czy w ogóle można edytować plik crona. Jeszcze nad tym się nie zastanawiałem

Problemy dla rozwiązania 2):
- wpisów może być tysiące. Czy skrypt obsłuży mi w ciągu minuty tysiące rekordów
- czy cron odpala się dokładnie co minute? Nie ma lagów? np. ostatnie wywołanie crona będzie w 3:59 (minuty:sekundy), zaś aktualne w 5:01 - jak widać cron odpalił się po minucie i dwóch sekundach, i w tym czasie stracił odpalenie dla minuty czwartej.

To są narazie luźne moje przemyślenia. Macie z tym jakieś doświadczenia? Macie jakieś pomysły?
posiadacz
ja bym zrobił na sposób 2.

Przy każdym odpaleniu zapisujesz datę ostatniego odpalenia albo datę nastepnego odpalenia.
W zapytaniu sprawdzasz czy data ostatniego odpalenia + okres odpalenia już minął albo czy data następnego odpalenia już minęła.

Powodzenia!
nospor
Jest w tym jakiś sens.
Jakieś inne propozycje?
d3ut3r
Co do konfliktu z czasem wykonywania to mogą wyjść cyrki smile.gif, CRON uruchomi 2 procesy jeżeli pierwszy się nie zakończył i drugi zacznie działać na danych których pierwszy jeszcze nie zmodyfikował może powstać jakiś problem logiczny.

Tak czy inaczej wszystko zależy od serwera np. na home.pl żeby zrobić zadanie CRON trzeba utworzyć plik o odpowiedniej nazwie (czas uruchamiania co 5 minut) jeżeli hosting udostępnia jakieś API do panelu zarządzania kontem to raczej nie będzie problemu z dodaniem zadań do CRONTAB ew. wykonanie polecenia wiersza poleceń w celu dodania zadania.

To tylko takie gdybanie gdyż wiele zależy od konfiguracji serwera i uprawnień jakie posiadasz.
wookieb
Jak dużo "akcji" na raz przewidujesz?
nospor
Cytat
Co do konfliktu z czasem wykonywania to mogą wyjść cyrki , CRON uruchomi 2 procesy jeżeli pierwszy się nie zakończył i drugi zacznie działać na danych których pierwszy jeszcze nie zmodyfikował może powstać jakiś problem logiczny.
To akurat nie problem dla mnie

Cytat
Tak czy inaczej wszystko zależy od serwera np. na home.pl żeby zrobić zadanie CRON trzeba utworzyć plik o odpowiedniej nazwie (czas uruchamiania co 5 minut) jeżeli hosting udostępnia jakieś API do panelu zarządzania kontem to raczej nie będzie problemu z dodaniem zadań do CRONTAB ew. wykonanie polecenia wiersza poleceń w celu dodania zadania.

To tylko takie gdybanie gdyż wiele zależy od konfiguracji serwera i uprawnień jakie posiadasz.
Serwer dedykowany, żaden tam home.pl. Mam pełen dostęp do crona
d3ut3r
w takim razie ja bawiłbym się z wykorzystaniem CRONTABA do każdego zadania.
nospor
Cytat
Jak dużo "akcji" na raz przewidujesz?
Docelowo to pewnie tysiące. Na początku "nędzne" dziesiątki wink.gif
Każda "akcja" będzie wykonywana jako oddzielny proces w tle. Przynajmniej tak by było w wersji nr 2
m44
Jak dedykowany to może demon w php odpalany przez crona. Jeśli zwiększy się liczba zdarzeń, można uruchomić dwa lub więcej demonów obsługujących zdarzenia w wyznaczonych godzinach.
nospor
Cytat
w takim razie ja bawiłbym się z wykorzystaniem CRONTABA do każdego zadania.
Przyznam szczerze, że nie szukałem jeszcze odpowiedzi na pytanie, które teraz ci zadam:
A mogę bez problemu edytować ogólny plik crontaba jak normalny plik tekstowy? Z tego co szczątkowo czytałem, w zależności od systemu zapiski crontaba mogą leżeć w totalnie różnych miejscach
d3ut3r
Hmm generalnie edycja CRON w jednym moim skrypcie wygląda tak:

1. Tworzę wpis z pojedynczym zadaniem wg zasad http://www.cyberciti.biz/faq/how-do-i-add-...x-or-unix-oses/
2. Następnie wykonuję polecenie crontab nazwa_pliku.txt powoduje to dopisanie zadania z pliku tekstowego do tablicy cron, w ten sposób nie musisz sam lokalizować pliku z tablicą ponieważ sam system wszystko dopisze w zależności od własnej konfiguracji.

nospor
A jak usuwasz jakiś wpis?
d3ut3r
No właśnie, na początek przepraszam wprowadziłem w błąd za szybko chciałem odpisać smile.gif

generalnie jest tak, że polecenie crontab nazwa_pliku.txt nadpisuje tablicę cron a nie dopisuje do niej. Więc generujesz cały plik ze wszystkimi zadaniami i wykonujesz polecenie. Przydatny jest przełącznik -u nazwa_usera wtedy edytujesz zadania tylko dla danego użytkownika.

A tutaj przykład jak dopisać tylko jedno zadanie do pliku.

http://stackoverflow.com/questions/610839/...-a-new-cron-job
nospor
Użytkownicy nie mają kont w systemie, więc opcja z oddzielnym crontab odpada.
Generowanie całego pliku crontaba przy każdej zmianie jakiegoś harmonogramu to też średnio fajne rozwiązanie.
W pliku tym, znajdować się też będą wpisy, który dodałem ręcznie (jak rozsyłka maili itp).
Rozwiązaniem by było, aby moje ręczne wpisy trzymał na userze X, a automatyczne na userze Y - to by było jakieś wyjście.
Kolejny problem jaki mi się tu widzi to co będzie w sytuacji, że w tym samym czasie dwie osoby zmienią jakiś harmonogram? Przy crontabie liczącym tysiące wpisów nie będzie przypadkiem problemu gdy naraz będę próbował załadować dwa duże pliki z wpisami?
wookieb
Więc pozostaje wszelkiego rodzaju DEMON wyszukujący co sekundę nowych zadań. Rozwiązanie najwygodniejsze. Kwestia tylko W CZYM napisać taki DEMON. Nie sądzę aby PHP był do tego celu dobrym rozwiązaniem.

Zabrzmi strasznie lamersko ale ja bym to zrobił nawet w NODEJS. Jeżeli ktoś ma inną propozycję z chęcią wysłucham.
d3ut3r
hmm można by pokusić się o napisanie klasy do obsługi crontab generalnie polecenie crontab -l zwróci listę aktualnych zadań można na jej podstawie utworzyć tablicę z zadaniami następnie na niej operować i za pomocą crontab nazwa_pliku zapisywać czyli po wczytaniu tablicy możemy dowolnie na niej operować dodawać / usuwać zadania.

Chyba jednak zadanie będzie trudniejsze niż się wydawało smile.gif Rozwiązaniem wydaje mi się byłaby synchronizacja CRONTAB za pomocą CRON smile.gif wyglądałoby to mniej więcej tak, że dajesz panel do edycji
zadań te zadania zapisują się w bazie a po każdym updacie dajesz informacje że zmiany zostaną naniesione w ciągu najbliższych 5 minut i zadanie CRON uruchamiane co 5 minut uaktualnia crontab który już działa zgodnie z harmonogramem poszczególnych zadań. Zaimportowanie nawet dużego pliku do crontab nie powinno zająć dużo czasu. Jeżeli dodasz do tego jakiś mechanizm który co te 5 minut będzie sprawdzał czy update cron jest konieczny to i tak moim zdaniem będzie to wydajniejsze niż 2 sposób.
nospor
Cytat
Rozwiązaniem wydaje mi się byłaby synchronizacja CRONTAB za pomocą CRON wyglądałoby to mniej więcej tak, że dajesz panel do edycji
zadań te zadania zapisują się w bazie a po każdym updacie dajesz informacje że zmiany zostaną naniesione w ciągu najbliższych 5 minut i zadanie CRON uruchamiane co 5 minut uaktualnia crontab który już działa zgodnie z harmonogramem poszczególnych zadań. Zaimportowanie nawet dużego pliku do crontab nie powinno zająć dużo czasu. Jeżeli dodasz do tego jakiś mechanizm który co te 5 minut będzie sprawdzał czy update cron jest konieczny to i tak moim zdaniem będzie to wydajniejsze niż 2 sposób.
Hm... to jest jakiś pomysł smile.gif

@wookieb demon co sekunde? Po co?
wookieb
TFU. Co minutę oczywiście
yevaud
teoretycznie mozna byloby pisac swoje rozwiazania ktore moglyby robic cuda forkujac sie po systemie, izolujac odpalane procesy, nasluchujac, synchronizujac itp itd.
ale moim zdaniem najlepiej oprzec sie na juz dzialajacym rozwiazaniu -> tzn. cronie.

wpisy do crona trzymalbym w bazie danych, skrypt ktory cos dodaje/odejmuje modyfikuje tylko ta baze danych.
W cronie(pewnie tez nawet w bazie) dodalbym skrypt ktory co minute aktualizowalby plik crona na podstawie bazy. Aktualizacje zrobilbym w ten sposob, ze pisalbym do jakiegos tmp i pozniej podmienial plik(zeby lockowac jak najkrocej)

Najgorsza czesc roboty tutaj odwala sam cron, rozwiazanie dobrze sie skaluje, gdyby faktycznie okazalo sie po jakims czasie, ze sam cron sie nie wyrabia z procesami, to takie rozwiazanie latwo mozna uzupelnic o "swojego crona", ale prawdopodobnie cron wystarczy wiec YAGNI wink.gif

Minus: na wyniki aktualizacji trzeba byloby czekac 2 minuty!, ale mysle ze to naprawde maly problem.

btw. cron z tego co wiem sprawdza swoj plik w okienkach 30 sekund, wiec fajnie jakby udalo sie wygnerowac plik w okienku 0-29 sekund smile.gif

nospor
@wookieb Czym będzie się różnił demon od skryptu odpalanego co minutę, który będzie robił to samo co demon?

Cytat
wpisy do crona trzymalbym w bazie danych, skrypt ktory cos dodaje/odejmuje modyfikuje tylko ta baze danych.
W cronie(pewnie tez nawet w bazie) dodalbym skrypt ktory co minute aktualizowalby plik crona na podstawie bazy. Aktualizacje zrobilbym w ten sposob, ze pisalbym do jakiegos tmp i pozniej podmienial plik(zeby lockowac jak najkrocej)

Najgorsza czesc roboty tutaj odwala sam cron, rozwiazanie dobrze sie skaluje, gdyby faktycznie okazalo sie po jakims czasie, ze sam cron sie nie wyrabia z procesami, to takie rozwiazanie latwo mozna uzupelnic o "swojego crona", ale prawdopodobnie cron wystarczy wiec YAGNI

Minus: na wyniki aktualizacji trzeba byloby czekac 2 minuty!, ale mysle ze to naprawde maly problem.

@yevaud czyli napisałeś to samo co w ostatnim poście d3ut3r smile.gif
To że trzeba by poczekać na wynik aktualizacji to faktycznie żaden problem
wookieb
W demonie nie będzie opóźnień spowodowanych edycją pliku crontab. Poza tym dzięki niemu możesz łatwo zejść poniżej CRONTAB-owego narzutu zdefiniowania odpalania zdarzenia z dokładnością "tylko" co do minuty.
nospor
Przy wersje nr 2 też tego opóźnienia nie będzie. A demon o którym wspominasz to nic innego jak wersja nr 2 smile.gif
Co do narzutu minuty to akurat w moim przypadku jest wystarczające. I tak planuję dać we własnym cronie nie częściej nić co 15 minut.
zordon
ja bym zrobił jeden wpis w cronie - który co minutę odpala skrypt.

zadania trzymałbym w bazie, z datą i priorytetem. Trzeba by napisać funkcję która wybiera kolejność na podstawie daty (trzeba uprzywilejowywać rekordy jeśli data minęła a rekord nie "załapał się" już parę razy do skryptu) i priorytetu.
Rekordy musiały by wykonywać się w pętli pojedynczo, blokując się dla innych wywołań skryptu. Aby nie było problemów z zawieszaniem skryptu można by dać jakiś zwiększany licznik i przerywać po osiągnięciu limitu.
Każdy "nowy" skrypt odpalony przez crona brałby na podstawie opisanej wcześniej funkcji tylko 1 rekord i go od razu blokował, więc byłaby pewność, że skrypty nie będą pracowały na tym samym rekordzie. W przypadku zablokowania rekordu i błędu można zapisywać datę blokady i np puścić drugi skrypt który odblokowywałby wszystkie rekordy którzych czas od założenia np > 5min.

Kiedyś napisałem coś podobnego i działa, chociaż nie wiem jak z wydajnością w porównaniu z innymi przedstawionymi tu rozwiązaniami.
nospor
Ok, wstępnie zrobiłem opcję nr 2. Zależało mi w tej chwili na czasie a opcję numer dwa skleciłem w 15 minut.
Dziękuję wszystkim za uwagi. Wszakże nie ze wszystkich teraz skorzystałem ale pomysły były dobre i na pewno w przyszłości z nich skorzystam
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.