Cron and queue
Membership expiration is handled in two steps: hook_cron finds memberships that need to be expired and enqueues them; a queue worker processes each item by calling the membership’s term plugin’s expire() method.
hook_cron
Implementation: Drupal\crm_membership\Hook\CoreHooks::cron()
File: src/Hook/CoreHooks.php
On each cron run, the hook:
- Memberships with no current periods — Finds all memberships with
statusnot expired andcurrent_periodsempty. These are treated as needing expiration (e.g. they were active but something left them without a valid period). - Memberships with only expired periods — Finds memberships that are not yet marked expired but whose referenced
current_periodsall havedate_range.end_valuein the past. So if at least one period is still active, the membership is skipped; if every current period has ended, it is queued. - Enqueue — For each membership ID from (1) and (2), creates one item on the queue
crm_membership_expirationwith payload['crm_membership_id' => $membership_id].
The hook does not change any membership or period itself; it only adds items to the queue. Date comparison uses the storage timezone and datetime format from DateTimeItemInterface.
Queue worker
Queue ID: crm_membership_expiration
Class: Drupal\crm_membership\Plugin\QueueWorker\MembershipExpiration
File: src/Plugin/QueueWorker/MembershipExpiration.php
Cron time: 60 seconds (so cron will process this queue for up to 60 seconds per run).
For each queue item:
- Reads
crm_membership_idfrom the item data. - Loads the
crm_membershipentity. - Gets the membership’s Membership Term plugin via
$membership->getMembershipTerm(). - Calls
$membershipTerm->expire().
The term plugin’s expire() is responsible for updating the membership (e.g. set status to expired, remove or adjust current_periods, and save). The queue worker does not perform any other logic.
Summary
| Step | Component | Action |
|---|---|---|
| 1 | CoreHooks::cron() |
Find memberships without current periods or with only expired periods; enqueue each by ID. |
| 2 | MembershipExpiration::processItem() |
Load membership, get term plugin, call expire(). |
Ensure cron is running (e.g. via system cron or Drupal’s cron) so that expirations are processed regularly. The 60-second cron time limit means only a subset of queued items may be processed per run if there are many expirations.