This actually started out as a single idea, then it blossomed into three ideas, and then at the very end of my thinking, it reduced to two ideas. Apparently I’d forgotten why I’d written a certain high profile module, and it took me a good 30 minutes to realize I was approaching it from the slightly wrong angle.

In order to preserve that flawed logic, I will describe my train of thought: One of the things I have long wanted, but have not yet gotten around to doing, is to allow scheduling based upon the Node Queue. One of the original design points, and the reason it’s even called a queue is that it’s supposed to be a bucket that a site maintainer can drop nodes in. They go in on one end, and eventually they go out another end.

Right now, the primary method of a node falling out of the queue is when the queue is full, and the front node is popped off automatically. This is nice and all, but it’s actually not the most important use.

See, one feature I have on Assign Blame (and sadly don’t use due to lack of content) is the Goat of the Week, which auto publishes articles on a weekly basis. Ideally, there would be a queue of articles (get it, a queue) already ready to go, and every Monday, pow, the system publishes one. And it does that, sort of. Not terribly well. But that’s the general idea I had.

So the current idea goes like this: A module, uncreatively named Node Queue Scheduler, creates some number of schedules. The part that took me awhile to come around to is that it really shouldn’t be a Node Queue, it should be a View; because it’s already possible to make a View that is exactly what the Node Queue should be, but so many other things can be done with a View.

So each schedule record requires the following data:

  • An id. Pretty much required for tables like this.
  • A view name or view id. Names are friendlier; ids slightly faster.
  • A max number of nodes to return; when doing a programmatic view, the maximum nodes is determined here. For the basic nodequeue case, it’d likely be 1, but this could also do maintenance tasks.
  • An interval. In my mind, it’s two fields. The first field is a number, the second field is one of seconds, minutes, hours, day, weeks, months. This is more human readable.
  • The time this schedule will next run; updated programmatically of course.
  • A list of actions (from the actions module) to perform.

So what we have here, then, is a system where I can create a recurring schedule. Let’s say I run it once a week. hook_cron() does a query to see which of these schedules are now available to be run (SELECT * FROM view_scheduler WHERE next_run < now). For each schedule, it loads the view, and then for each node the view returns, it passes the actions list off.

It needs to be able to manually adjust the next fire time for each schedule; just because I say once a week doesn’t mean I want it once a week from when I entered it. And it needs to update the interval from when it should have run, not when it actually runs. If your cron.php only gets called once an hour, it could get run 59 minutes and 59 seconds late. If your task is run daily at midnight, it wouldn’t be very long before it’s run in the middle of the day. That’d be wrong.

Ok, so that’s idea number one. The second one is either the logical extension of that, or in fact the more simple version. Right now, we have the scheduler module out there, but honestly it kind of sucks.

Instead, what I envision is a module that adds a tab to a node. (I love adding tabs to nodes for stuff like this; why? Because you don’t need edit permissions to be able to utilize it). So anyway, it adds a tab to the node. The tab allows any number of scheduler entries; the user can add and remove these entries. Each schedule entry has the NID, an execute time, and…yes, a list of actions to perform, a la the actions module. Now, the one thing that’s still missing, I think, is that in this case, we really would want the actions module to support action groups, where various actions can be bundled together to provide a larger sort of macro-action that is easier for admins to select.

So the question is — anybody want to tackle these? Neither of them should actually be all that long. All of the actual work done is being done by other modules, and all that these modules really do is provide a UI and the cron hook which then tells other modules to do their thing. Now, UI stuff always takes a little more code than I’d like to think. You need list/add/edit/delete functions, plus the menu stubs for each. Still, the database entries are quite simple, and none of the functions require staggering amounts of data. The hardest problem here may be translating 1 month into an actual time, since 1 month is a different unit of measurement depending upon what month it is. But that’s solvable.

If no one volunteers I’ll get around to these…eventually. Sooner if someone sees a need for this stuff and pays for it, but right now I have quite a lot on my stack. These aren’t too hard, so I thought that perhaps someone a little newer to Drupal and eager to learn would be interested. I would be more than willing to provide guidance and code review.

Comment, contact or email if interested!

Schedules Module

I might have what you're looking for, I've been working on a schedule API for a while. Originally developed for the eNewsletter module, I repurposed it to be a generic library for dealing with schedules.

The data schema looks like this...

-- Schedules table --

Schedule Id

Schedule Title: A human readable label.

Type: Type of service being scheduled - useful for querying all schedules of a certain type without requiring JOINs.

Publication ID: The ID of the publication/action being scheduled

Start: If content is to be included from before first publication/action, when should content start being included.

First: Time of first publication/action.

Next: Time of next publication/action.

Last: Time of last publication/action.

Every: Schedule interval - month/day/hour/manual

Frequency: Unit value of interval, e.g. 5 (x Every)

-- schedules_action table --

Schedule Id
Type (as above)
Publication ID (as above)
Schedule Id
Publication Time: timestamp of action.

schedules_action table allows for a history of scheduled actions.

The project is available here - but if you're interested send me an email and I'll give you the latest version, which is fully functional, but I can't release it until I create an update script for legacy users.

Goodness!

You do indeed seem to have pretty much everything I'm looking for, except for the ability to act on a view. In fact, the only thing I don't really see is how you tie a schedule to something at all? I have to assume that's in there, though, and it becomes just a matter of UI...

$publication_id and $type is

$publication_id and $type is used to tie a schedule with whatever you want to tie it with....

e.g. to get a schedule:

$schedules = schedule_select_schedules($type, $publication_id);

There's a function that checks if it's time to act on a schedule, and returns TRUE or FALSE - the calling module then takes whatever action it wants.

I still need to do some work on reducing the amount of APIs than need to be called and shift more of the processes to work internally.

schedule.module

scheduler.module is a bit old but it does the features that you describe in a simpler way. would be nice if someone updated it and integrated with actions.module

Scheduler is...

not very well done, IMO. Which is why I'd rather start from a fresh base. Though I like the schedules.module above, and am happy to work with it, I think.

Good!

Thank you for directing me to this page, Merlin. I am encouraged by the level of thought and effort already invested in the concept of scheduling actions.

You mentioned above an action group module. I agree that we need something like that. In fact, the workflow module could call groups of actions when nodes change state. If the workflow module is up-to-date, it may even serve as a basis for the new module.

I have a couple clients who need something along these lines. So I am willing to contribute code, comments, and encouragement.

At the moment I have

At the moment I have contributed thoughts, ideas and an existing codebase. What is needed at this point is for someone to take charge and do what needs to be done to make it all work. You have a need AND you have the ability, that puts you in an excellent position to do this.

I am happy to provide help, advice and support in the endeavor because I believe this is a highly useful featureset, regardless of how it comes about. The more open it is, the more modules can take advantage of it. As I said above, I felt the scheduler API was a great foundation, and all it really needs, I think, is to be run with.

Post new comment

The content of this field is kept private and will not be shown publicly.