2

I want to re-save all user accounts on my site weekly because I wrote some code in hook_user_presave() that I want to update every week.

Specifically, my hook_user_presave() code updates the values of some fields like Total number of comments posted and Total number of articles posted, and it sends an email if the user hasn't logged in for more than a month. (This info is only available to the site admin, which is me, so it doesn't need to be perfectly in sync.)

Right now, I have a View with VBO that I can use to re-save all the user accounts manually. I want to automate this process by saving all the users automatically at 3 am on Sunday.

How do I schedule all user accounts to be saved? Is this a task for Queue API or does core/contrib provide something more appropriate for this use case?

5
  • Presave runs on updates too. So that will skew your totals unless you want to count edits.
    – No Sssweat
    Oct 15 '20 at 10:31
  • Why not do the +1 to the user field when a new node or comment is inserted?
    – No Sssweat
    Oct 15 '20 at 10:32
  • 1
    @NoSssweat I anticipate that the average user on the site will perform 25-200 actions per day that result in something counted by my hook_user_presave() code (mainly because this includes Flag module flaggings). The fields that are set by the code are only needed to send the email, which won't happen more than once a week, so I want to minimize load on the server by only saving the user accounts (automatically) once a week or so instead of every time. Oct 15 '20 at 10:40
  • 1
    You could write a drush command that leverages the queue api, and then call it once a week and process the queue yourself. I wrote something similar recently.
    – Kevin
    Oct 15 '20 at 11:12
  • Yeah sounds like hook_cron and a QueueWorker plugin. Check this article sitepoint.com/… but replace hook_entity_insert with hook_cron and in there query all user IDs and add them to the queue.
    – leymannx
    Oct 15 '20 at 13:31
1

Ultimate Cron

Provides a UI where you can schedule all the cron jobs. Example:

enter image description here


Job Scheduler

Provides an API to schedule jobs.

Simple example:

// Declare scheduler.

  function example_cron_job_scheduler_info() {
    $schedulers = [];
    $schedulers['example_unpublish'] = [
      'worker callback' => 'example_unpublish_nodes',
    ];
    return $schedulers;
  }

// Add a job.

  $job = [
    'name' => 'example_unpublish',
    'type' => 'story',
    'id' => 12, // must be unique
    'crontab' => * 3 * * 0, // Every Sunday at 3 AM
    'periodic' => TRUE, // set to false if you want to just run once.
  ];
  $service = \Drupal::service('job_scheduler.manager');
  $service->set($job);

// Work off a job.

  function example_update_users_total(\Drupal\job_scheduler\Entity\JobSchedule $job) {
    // Do stuff.
  }

There is more examples & info in the READ.ME, so read it.


Important

It's important to note that the above in reality is scheduled to run the next time someone visits the site after 3am on Sunday. So if no one visits the site until say 9am on Sunday, it will not run until 9am. This is because Drupal's Cron can only run when Drupal is initialized.

The only way to be sure that it runs at 3am, you have to set a cron job in your server (just know that your server time may not be the same as your timezone, so you'll have to check that), using the crontab -e command (for linux) will open the file where you can add jobs to the server. Have this server job run a file that contains code that performs a GET request on your site. OR alternatively a custom Drush command like Kevin commented.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.