Exam Area: Area 1 – Product Knowledge (15%) Reference: https://docs.developers.optimizely.com/content-management-system/docs/scheduled-jobs
/episerver/cms/admin → Scheduled Jobs
The Scheduled Jobs admin page lists all registered scheduled jobs (both built-in and custom).
For each job, the admin panel shows:
| Field | Description |
|---|---|
| Name | Display name of the job |
| Status | Idle / Running / Failed |
| Last run | Timestamp of last execution |
| Next run | Calculated next execution time |
| Interval | How often the job runs |
| Enabled | Whether the job is active |
Actions available:
| Job | Purpose |
|---|---|
| Archive function | Archives old content versions beyond configured limit |
| Clear Thumbnail Properties | Regenerates image thumbnails |
| Fetch data from Remote Sites | Pulls content from mirroring sources |
| Link validation | Scans for broken internal/external links |
| Mirroring service | Mirrors content to another CMS instance |
| Rebuild global secondary index | Rebuilds the global search index |
| Remove abandoned BLOBs | Deletes orphaned binary files (media without content items) |
| Remove old content versions | Prunes old saved versions per content item |
| Remove old temporary BLOBs | Cleans up temporary upload files |
| Subscription | Sends notification emails for subscribed content |
| Crawl for link changes | Updates link database |
Each job stores the last execution result as a status message. View it in Admin:
Admin → Scheduled Jobs → Click job name → View log
Shows:
- Start time
- End time
- Status (Success / Failed)
- Output message (returned by Execute())
- Exception details (if failed)
See 04_Framework_Components/03_scheduled_jobs_dev.md for implementation details.
// Minimal example
[ScheduledPlugIn(
DisplayName = "Refresh Product Cache",
GUID = "E5C9D2F4-1234-5678-ABCD-0011223344FF",
DefaultIntervalType = ScheduledIntervalType.Hours,
DefaultInterval = 6)]
public class RefreshProductCacheJob : ScheduledJobBase
{
private bool _stopSignaled;
public RefreshProductCacheJob()
{
IsStoppable = true;
}
public override void Stop() => _stopSignaled = true;
public override string Execute()
{
var count = 0;
foreach (var product in GetProducts())
{
if (_stopSignaled) return $"Stopped after {count} products.";
RefreshCache(product);
count++;
}
return $"Refreshed cache for {count} products.";
}
}
public enum ScheduledIntervalType
{
None, // No automatic scheduling
Minutes,
Hours,
Days,
Weeks,
Months
}
In a multi-server (load-balanced) environment, scheduled jobs run on one server at a time to prevent duplicate execution:
Server A: Running job ─────── (leader)
Server B: Waiting ─────────── (follower, skips execution)
Server C: Waiting ─────────── (follower, skips execution)
// Run a scheduled job from code (e.g. from a controller action)
public class AdminController : Controller
{
private readonly IScheduledJobRepository _jobRepository;
private readonly IScheduledJobExecutor _jobExecutor;
public AdminController(
IScheduledJobRepository jobRepository,
IScheduledJobExecutor jobExecutor)
{
_jobRepository = jobRepository;
_jobExecutor = jobExecutor;
}
public async Task<IActionResult> RunJob(Guid jobGuid)
{
var job = _jobRepository.Get(jobGuid);
if (job == null) return NotFound();
await _jobExecutor.StartAsync(job, new JobExecutionOptions
{
Trigger = ScheduledJobTrigger.User
});
return Ok($"Job '{job.Name}' started.");
}
}