News:

Wondering if this will always be free?  See why free is better.

Main Menu

How to create Scheduled Tasks in SMF 2.0

Started by Arantor, August 09, 2009, 03:30:45 PM

Previous topic - Next topic

Arantor

Judging by the number of mods that don't use scheduled tasks in 2.0, it seems to be that there is a little bit of confusion on how to create them. So, here goes - with thanks to JBlaze for getting me started on it in the first place.

Any scheduled task requires 3 basic things: code to run, a description in the language files, and an entry in the database.

For the purpose of this, I'm actually going to talk you through a simplified version of my Auto Lock Old Topics mod, where instead of locking threads configurably, we'll just say we lock every thread that hasn't been replied to in 30 days.

The very first thing we need to do is give our task an identifier. It doesn't have to be special but needs to be short and as unique as you can be. I used 'autoLock' for mine, so we'll continue to use that here to keep it straightforward.

Description

Let's start with the easiest thing: description. Each scheduled task has a name and a quick description, which you can see in the Scheduled Tasks part of the Admin area in 2.0. The name is also a link to configure when the script should run, and we don't want to get into modifying things we don't need to for it.

In fact, adding a description is nice and easy, you just have to add 2 lines to ManageScheduledTasks.english.php in the theme (for the budding mod authors out there, it's $languagedir/ManageScheduledTasks.english.php you want, plus any other language variations)

Here's where the identifier comes in. We create two language strings, scheduled_task_{identifier} and scheduled_task_desc_{identifier} and add them to $txt.

So to the bottom of ManageScheduledTasks.english.php, I would add:

$txt['scheduled_task_autoLock'] = 'Auto Lock Old Topics';
$txt['scheduled_task_desc_autoLock'] = 'Locks topics that have not been replied to in 30 days.';


And bippity-boppity-boop, that's that bit done.

Code to run

Having set up the description of the mod, we do actually need to write some code that would get run when our task is called for.

The key thing here is the name of the function, and location. It should live in Sources/ScheduledTasks.php (for you mod authors, $sourcedir/ScheduledTasks.php), and go by the name of scheduled_{identifier}. So with our autoLock identifier, we want something like:


function scheduled_autoLock()
{
global $modSettings, $sourcedir, $mbname, $txt, $smcFunc, $scripturl;

$timestamp = time() - (30 * 86400);
$query = 'UPDATE {db_prefix}topics, {db_prefix}messages
SET {db_prefix}topics.locked = 1
WHERE {db_prefix}topics.id_last_msg = {db_prefix}messages.id_msg
AND {db_prefix}messages.poster_time <= {int:timestamp}';

$result = $smcFunc['db_query']('',
$query,
array(
'timestamp' => $timestamp,
)
);

return true;
}


You only have to inherit what variables you actually need, though I tend to make sure all the variables I might need are handy, and the code simply needs to run, returning true if successful, and false if not. You can check out the fuller code in the mod I mentioned, which also does it on a per-board level.

So, with that we have the description for our task, and the code for it to run.

Database work

We do also have to do one last thing - tell SMF about the task that needs to be run. Code alone is not sufficient here for that. For the mod authors out there, this last bit would be managed via an install.php and uninstall.php script as part of your mod install. Again, the technique is shown in the master version of the Auto Lock Old Topics mod.

Adding it is a simple case of adding a new row to the scheduled_tasks table, perhaps smf_scheduled_tasks. The query you'll use with $smcFunc takes the form of:


INSERT INTO {db_prefix}scheduled_tasks (id_task, next_time, time_offset, time_regularity, time_unit, disabled, task)
VALUES (NULL, 0, 0, 1, "d", 0, "autoLock")


(Of course, if we're being proper, we should be using $smcFunc['db_insert'] instead of $smcFunc['db_query']. But this way you can see what the columns are and how they relate to each other.)

Just let's quickly step through the columns:

  • id_task is a numeric identifier for the row. We don't know this yet, and it's going to be assigned by SMF anyway, so leave that as NULL.
  • next_time is the next time SMF is due to run the task. We set this to 0 because the task hasn't been run before.
  • time_offset is the offset to run the task against, which should be the same as the forum time.
  • time_regularity is the number of times per unit that this runs. For example, if running once per day, this is 1 - related to the next topic.
  • time_unit is the time period considered for running the task. Supports 'm', 'h', 'd', 'w', for per minute, per hour, per day, per week. If you want to run the task daily at a set time for example, you have time_regularity as 1, and time_unit as 'd'. Once every 2 days, regularity = 2, time_unit = 'd'.
  • disabled reflects if the task is disabled or not, 0 for not disabled (enabled) and 1 for disabled.
  • task is the task identifier, in our case here 'autoLock'.

Once all of this is done, your scheduled task should be available to set what time you want it to run (since it will likely be different for every user)


Hopefully that's helped - if you have any questions please do ask.

aED

Hi Arantor,

Sorry to bump this but is there  any way I can make a scheduled task to run every first day of the month?

Arantor

No, you'd have to have it run every 4 weeks or every 30 days. Or when it runs, have it recalculate the next interval.

aED

hehehe :P thanks I Just figured it out after posting my message:)

Arantor


butchs

I have been truly inspired by the SUGGESTIONS as I sit on my throne and contemplate the wisdom imposed upon me.

treams

thanks for this.

i am using this guide and your auto purge mod as a basis for my first mod to delete the reference for MOVED topics to help keep the board i frequent a little cleaner.

Arantor

Or you could use the Redirection Topics mod I wrote a while ago to automate that process too ;)

treams

ha well doesnt that beat all. i searched and searched the mod site for something like this and couldnt find what i wanted. i never would have thought to use "redirection" as a keyword though.

well ya saved me a ton of time. i guess i will have to think of something else to write.

Arantor

Well, the moved topics are redirection topics, they direct you to where you want to go, I also made it actually do a redirect as well.

Robbo_ now maintains the mod though.

Don't give up though, there's plenty of exciting mod possibilities :)

butchs

I would assume that with some coding you can externally estimate then date and then insert new values into the database once a month?
:o
I have been truly inspired by the SUGGESTIONS as I sit on my throne and contemplate the wisdom imposed upon me.

Arantor

Sure you can. But it's easier if you don't have to keep track of such things.

butchs

I have been truly inspired by the SUGGESTIONS as I sit on my throne and contemplate the wisdom imposed upon me.

Arantor

That's the thing, creating a scheduled task is, as above, basically a fire-and-forget situation, you define the function and matching language string, insert a row in a DB and you're basically done.

Mick.

Arantor, great write up brother.

I have a question and it may be related to aED'd reply #2.

Scheduled tasks is not possible twice a day huh?     I have a mod idea that i currently do manually.   It has to do with members currently online.

Arantor

Sure it is. Once every 12 hours - regularity 12, time unit h.

Mick.

Quote from: Arantor on May 05, 2010, 01:05:49 PM
Sure it is. Once every 12 hours - regularity 12, time unit h.

Excellent.

The idea is,......  see, i have the member currently online set to 60 minutes.  ...and, in the language file i changed: "Users active in past 60 minutes" to "Users online".... and changed in "features and option" the time threshold from 60 to 360.

Now it shows a lot more users online.   But late at night like most forums, activity is not great.  That's where the scheduled task comes in.  At whatever time set, say, midnight it will revert from 360 mins to 60 mins.   ....and maybe a clear cache with it.

Then in the morning say at 6am, it will revert from 60 mins to 360 mins again.

That's why asked if the schedule task can be a key player here.

Arantor

Sure, in that case you create two tasks, each to run daily.

Then you just set one to run at midnight, and one to run at 6am - since the time a task is run is configurable in the ACP (and isn't related to this tutorial directly)

Mick.

Quote from: Arantor on May 05, 2010, 01:34:37 PM
Sure, in that case you create two tasks, each to run daily.

Then you just set one to run at midnight, and one to run at 6am - since the time a task is run is configurable in the ACP (and isn't related to this tutorial directly)

I didnt mean to thread-jack ;)

Thanx Arantor, that cleared my questions.

Arantor

Well, it's relevant - how to use scheduled tasks in a slightly different way, it's all good :)

Zaine

Removed my last question and asking it in a better way :)

How should you handle if it your scheduled tasks errors?   I'm logging errors using log_error(); and returning false from the Scheduled task function but the interface still happily reports that the task completed successfully, even when logging a critical error.

I'm getting the errors in the error log, which is good, but I was expecting to see that interface warn me that the manual run failed.


emanuele

Hi Zaine,

it's the first time for me looking into scheduled tasks, but as far as I can understand from the code it seems that if the scheduled function returns false the task should not be logged:
Code (from ScheduledTasks.php lines 124-129) Select
// Do the task...
$completed = call_user_func('scheduled_' . $row['task']);

// Log that we did it ;)
if ($completed)
{


Take a peek at what I'm doing! ;D




Hai bisogno di supporto in Italiano?

Aiutateci ad aiutarvi: spiegate bene il vostro problema: no, "non funziona" non è una spiegazione!!
1) Cosa fai,
2) cosa ti aspetti,
3) cosa ottieni.

DanCarroll

Here's a tip for anyone looking to run a task on a given day of the month such as the first.

Just schedule your task as a daily and do a check at the beginning to see if it is the first and then decide what code to run.

Iomega0318

Can this be used to run a link, I have a cron job I would like SMF to handle and was wanting to schedule it for once a week. However the cron job has a link for it, and before you ask, my server won't let me run cron jobs normally..
UOFreeshards.net
UOFreeshards.net 2.1 Aplha Test Site
"I believe in Christianity as I believe in the sun...
not because I see it but because by it I see everything else."
C.S. Lewis

Heed what I say, for it shall be mentioned only once.

live627

No. No way other than the code shown in the OP.

emanuele

fetch_web_data? :P

Of course I mean create a function that call fetch_web_data.


Take a peek at what I'm doing! ;D




Hai bisogno di supporto in Italiano?

Aiutateci ad aiutarvi: spiegate bene il vostro problema: no, "non funziona" non è una spiegazione!!
1) Cosa fai,
2) cosa ti aspetti,
3) cosa ottieni.

Acans

Very useful tutorial. Perfect for updating my member count across multiple shared forums :) (Instead of pressing that damn recount button everyday :P)
"The Book of Arantor, 17:3-5
  And I said unto him, thy database query shalt always be sent by the messenger of $smcFunc
  And $smcFunc shall protect you against injections and evil
  And so it came to pass that mysql_query was declared deprecated and even though he says he is not
  dead yet, the time was soon to come to pass when mysql_query shall be gone and no more

live627


DieGoO

I managed to create a scheduled task, but it seems like it isn't running automatically, or  at least, it doesn't show on the task log..

But if i run it manually it does show on the task log..

Did i miss something?

Arantor


DieGoO

Nevermind  :P .. After reading through the topic again, i figured out why it wasn't working..

live627


Arantor

You realise that the IT Crowd was practically a documentary rather than a comedy, right? ;)

live627


4Kstore

Sorry for the bump, but I need to ask for save some time, there is no hook actually for this? SMF 2.0?
I read something http://www.simplemachines.org/community/index.php?topic=510873.0

¡¡NEW MOD: Sparkles User Names!!!

live627


Arantor

I wrote this years ago. Off the top of my head there is no hook in 2.0, the one in 2.1 is not ideal IMO.

4Kstore


¡¡NEW MOD: Sparkles User Names!!!

PopUpSteve

Steve
"Even a broken clock is right twice a day, unless it's digital."

pirma

Very helpful article. Perfect for upgrading my new member count number across numerous contributed message boards.

alexetgus

Great !
I was looking for is exactly this topic!

Thank you very much ! ;)


PS :
Sorry for my english if it errors exists.
I'm french and i speak french. Only french. :(

Advertisement: