News:

SMF 2.1.4 has been released! Take it for a spin! Read more.

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.
Holder of controversial views, all of which my own.


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.
Holder of controversial views, all of which my own.


aED

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

Arantor

Holder of controversial views, all of which my own.


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 ;)
Holder of controversial views, all of which my own.


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 :)
Holder of controversial views, all of which my own.


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.
Holder of controversial views, all of which my own.


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.
Holder of controversial views, all of which my own.


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.
Holder of controversial views, all of which my own.


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)
Holder of controversial views, all of which my own.


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 :)
Holder of controversial views, all of which my own.


Advertisement: