This commit is contained in:
StellaOps Bot
2025-12-14 23:20:14 +02:00
parent 3411e825cd
commit b058dbe031
356 changed files with 68310 additions and 1108 deletions

View File

@@ -0,0 +1,54 @@
{
"$schema": "http://json.schemastore.org/template",
"author": "StellaOps",
"classifications": ["StellaOps", "Plugin", "Scheduler", "Job"],
"identity": "StellaOps.Plugin.Scheduler",
"name": "StellaOps Scheduled Job Plugin",
"shortName": "stellaops-plugin-scheduler",
"description": "A template for creating StellaOps scheduled job plugins",
"tags": {
"language": "C#",
"type": "project"
},
"sourceName": "MyJob",
"preferNameDirectory": true,
"symbols": {
"jobName": {
"type": "parameter",
"datatype": "text",
"description": "The name of the scheduled job (e.g., 'Cleanup' for CleanupJob)",
"defaultValue": "MyJob",
"replaces": "MyJob",
"fileRename": "MyJob"
},
"cronSchedule": {
"type": "parameter",
"datatype": "text",
"description": "Default cron schedule for the job",
"defaultValue": "0 0 * * *",
"replaces": "0 0 * * *"
},
"namespace": {
"type": "parameter",
"datatype": "text",
"description": "The root namespace for the plugin",
"defaultValue": "StellaOps.Plugin.MyJob",
"replaces": "StellaOps.Plugin.MyJob"
},
"pluginVersion": {
"type": "parameter",
"datatype": "text",
"description": "The initial plugin version",
"defaultValue": "1.0.0",
"replaces": "1.0.0-template"
}
},
"postActions": [
{
"description": "Restore NuGet packages required by this project",
"manualInstructions": [{ "text": "Run 'dotnet restore'" }],
"actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025",
"continueOnError": true
}
]
}

View File

@@ -0,0 +1,25 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using StellaOps.DependencyInjection;
using StellaOps.DependencyInjection.Validation;
namespace StellaOps.Plugin.MyJob;
/// <summary>
/// Registers MyJob services with the dependency injection container.
/// </summary>
public sealed class MyJobDependencyInjectionRoutine : IDependencyInjectionRoutine
{
/// <inheritdoc />
public IServiceCollection Register(IServiceCollection services, IConfiguration configuration)
{
// Register options with fail-fast validation
services.AddOptionsWithValidation<MyJobOptions, MyJobOptionsValidator>(
MyJobOptions.SectionName);
// Register the scheduled job
services.AddSingleton<IScheduledJob, MyJob>();
return services;
}
}

View File

@@ -0,0 +1,105 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using StellaOps.Plugin.Versioning;
// Declare plugin version for compatibility checking
[assembly: StellaPluginVersion("1.0.0-template", MinimumHostVersion = "1.0.0")]
namespace StellaOps.Plugin.MyJob;
/// <summary>
/// A scheduled job that runs on a configurable cron schedule.
/// </summary>
public sealed class MyJob : IScheduledJob
{
private readonly ILogger<MyJob> _logger;
private readonly MyJobOptions _options;
public MyJob(ILogger<MyJob> logger, IOptions<MyJobOptions> options)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_options = options?.Value ?? throw new ArgumentNullException(nameof(options));
}
/// <inheritdoc />
public string JobId => "my-job";
/// <inheritdoc />
public string DisplayName => "My Scheduled Job";
/// <inheritdoc />
public string CronSchedule => _options.CronSchedule;
/// <inheritdoc />
public async Task<JobResult> ExecuteAsync(JobContext context, CancellationToken cancellationToken = default)
{
_logger.LogInformation("Starting scheduled job {JobId} at {StartTime}", JobId, context.ScheduledTime);
try
{
// TODO: Implement your job logic here
await Task.Delay(100, cancellationToken);
_logger.LogInformation("Completed scheduled job {JobId}", JobId);
return new JobResult(
Success: true,
Message: "Job completed successfully",
ItemsProcessed: 0,
Errors: Array.Empty<string>());
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
_logger.LogError(ex, "Failed to execute scheduled job {JobId}", JobId);
return new JobResult(
Success: false,
Message: ex.Message,
ItemsProcessed: 0,
Errors: new[] { ex.Message });
}
}
}
/// <summary>
/// Represents a scheduled job that can be executed by the scheduler.
/// </summary>
public interface IScheduledJob
{
/// <summary>
/// Gets the unique identifier for this job.
/// </summary>
string JobId { get; }
/// <summary>
/// Gets the display name for this job.
/// </summary>
string DisplayName { get; }
/// <summary>
/// Gets the cron schedule expression for this job.
/// </summary>
string CronSchedule { get; }
/// <summary>
/// Executes the scheduled job.
/// </summary>
Task<JobResult> ExecuteAsync(JobContext context, CancellationToken cancellationToken = default);
}
/// <summary>
/// Context for job execution.
/// </summary>
public sealed record JobContext(
DateTimeOffset ScheduledTime,
DateTimeOffset ActualStartTime,
string? CorrelationId = null);
/// <summary>
/// Result of a job execution.
/// </summary>
public sealed record JobResult(
bool Success,
string? Message,
int ItemsProcessed,
IReadOnlyList<string> Errors);

View File

@@ -0,0 +1,43 @@
using System.ComponentModel.DataAnnotations;
namespace StellaOps.Plugin.MyJob;
/// <summary>
/// Configuration options for the MyJob scheduled plugin.
/// </summary>
public sealed class MyJobOptions
{
/// <summary>
/// The configuration section name.
/// </summary>
public const string SectionName = "Plugins:MyJob";
/// <summary>
/// Gets or sets the cron schedule expression.
/// Default: "0 0 * * *" (daily at midnight).
/// </summary>
[Required]
public string CronSchedule { get; set; } = "0 0 * * *";
/// <summary>
/// Gets or sets whether the job is enabled.
/// </summary>
public bool Enabled { get; set; } = true;
/// <summary>
/// Gets or sets the maximum execution time in minutes.
/// </summary>
[Range(1, 1440)]
public int MaxExecutionMinutes { get; set; } = 60;
/// <summary>
/// Gets or sets the batch size for processing items.
/// </summary>
[Range(1, 10000)]
public int BatchSize { get; set; } = 100;
/// <summary>
/// Gets or sets whether to continue processing on error.
/// </summary>
public bool ContinueOnError { get; set; }
}

View File

@@ -0,0 +1,31 @@
using StellaOps.DependencyInjection.Validation;
namespace StellaOps.Plugin.MyJob;
/// <summary>
/// Validates <see cref="MyJobOptions"/> configuration.
/// </summary>
public sealed class MyJobOptionsValidator : OptionsValidatorBase<MyJobOptions>
{
protected override string SectionPrefix => MyJobOptions.SectionName;
protected override void ValidateOptions(MyJobOptions options, ValidationContext context)
{
context
.RequireNotEmpty(options.CronSchedule, nameof(options.CronSchedule))
.RequirePositive(options.MaxExecutionMinutes, nameof(options.MaxExecutionMinutes))
.RequirePositive(options.BatchSize, nameof(options.BatchSize))
.RequireInRange(options.MaxExecutionMinutes, nameof(options.MaxExecutionMinutes), 1, 1440)
.RequireInRange(options.BatchSize, nameof(options.BatchSize), 1, 10000);
// Validate cron expression format (basic check)
if (!string.IsNullOrWhiteSpace(options.CronSchedule))
{
var parts = options.CronSchedule.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length < 5 || parts.Length > 6)
{
context.AddError(nameof(options.CronSchedule), "must be a valid cron expression with 5 or 6 fields.");
}
}
}
}

View File

@@ -0,0 +1,54 @@
# MyJob Scheduled Plugin
A StellaOps scheduled job plugin template.
## Getting Started
1. Update the `MyJobOptions.cs` with your job-specific configuration
2. Implement the job logic in `MyJob.cs`
3. Build and sign your plugin
## Configuration
Add the following to your `appsettings.json`:
```json
{
"Plugins": {
"MyJob": {
"Enabled": true,
"CronSchedule": "0 0 * * *",
"MaxExecutionMinutes": 60,
"BatchSize": 100,
"ContinueOnError": false
}
}
}
```
### Cron Schedule Examples
- `0 0 * * *` - Daily at midnight
- `0 */6 * * *` - Every 6 hours
- `0 0 * * 0` - Weekly on Sunday at midnight
- `0 0 1 * *` - Monthly on the 1st at midnight
## Building
```bash
dotnet build -c Release
```
## Signing
For production use, sign your plugin with Cosign:
```bash
cosign sign --key $COSIGN_KEY bin/Release/net10.0/StellaOps.Plugin.MyJob.dll
```
## Testing
```bash
dotnet test
```

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.0.0-template</Version>
<Description>StellaOps MyJob Scheduled Plugin</Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.0" />
</ItemGroup>
<!-- Reference StellaOps plugin infrastructure -->
<!-- Adjust paths based on your repository structure -->
<ItemGroup>
<ProjectReference Include="..\..\src\__Libraries\StellaOps.Plugin\StellaOps.Plugin.csproj" />
<ProjectReference Include="..\..\src\__Libraries\StellaOps.DependencyInjection\StellaOps.DependencyInjection.csproj" />
</ItemGroup>
</Project>