[SERVER-73548] Extend `ControllableJob` to support waking background jobs Created: 02/Feb/23  Updated: 16/Oct/23

Status: Open
Project: Core Server
Component/s: Internal Code
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major - P3
Reporter: Amirsaman Memaripour Assignee: Backlog - Service Architecture
Resolution: Unresolved Votes: 0
Labels: neweng
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Assigned Teams:
Service Arch
Participants:

 Description   

ControllableJob provides the following APIs to allow periodically running a background job:

/**
class ControllableJob {
public:
    // Starts running the job.
    virtual void start() = 0;
 
    // Pauses the job temporarily so that it does not execute until unpaused.
    virtual void pause() = 0;
 
    // Resumes a paused job so that it continues executing each interval.
    virtual void resume() = 0;
 
    // Stops the job, this function blocks until the job is stopped.
    virtual void stop() = 0;
};

This API could be extended to support waking background jobs:

class ControllableJob {
public:
    ...
    /*
     * Notifies the job to run so long as it's not paused or cancelled.
     * The job should stop (or skip) waiting and run as soon as possible.
     * Returns `false` if the job is already paused or cancelled, and `true` otherwise.
     */
    virtual bool wakeUp() = 0;
    ...
};

A possible implementation for PeriodicJobImpl could be based on a bool member that records wakeUp attempts:

bool PeriodicRunnerImpl::PeriodicJobImpl::wakeUp() {
    {
        stdx::lock_guard lk(_mutex);
        if (_execStatus != ExecutionStatus::RUNNING)
            return false;
        _notified = true;
    }
    _condvar.notify_one();
    return true;
}
...
void PeriodicRunnerImpl::PeriodicJobImpl::_run() {
    ...
    do {
        auto deadline = getDeadlineFromInterval();
        if (_clockSource->waitForConditionUntil(_condvar, lk, deadline, [&] {
            return _notified || _execStatus == ExecutionStatus::CANCELED || getDeadlineFromInterval() != deadline;
        })) {
            if (_execStatus == ExecutionStatus::CANCELED) {
                return;
            }
            if (std::exchange(_notified, false)) {
                break;
            }
        }
    } while (_clockSource->now() < getDeadlineFromInterval());
    ...
}



 Comments   
Comment by Matt Broadstone [ 02/Feb/23 ]

We will need a solution like this for PM-2459, a periodic job will be used to resize tenant queues and sometimes we need to wake it up sooner than its interval.

Generated at Thu Feb 08 06:24:59 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.