Initial commit: Add project files
ci / backend (push) Failing after 12s
ci / frontend (push) Failing after 19s
ci / static (push) Failing after 45s

This commit is contained in:
2026-08-02 05:15:36 +09:00
commit dcd1322d41
636 changed files with 122352 additions and 0 deletions
@@ -0,0 +1,44 @@
using KArtSell.BuildingBlocks.Time;
using KArtSell.Modules.ModelOperations.Domain;
namespace KArtSell.Modules.ModelOperations.Application;
public sealed class ModelOperationRequestService(
IApprovedModelContextReader contextReader,
IModelOperationRequestRepository repository,
IClock clock) : IModelOperationRequestService
{
public async Task<ModelOperationRequest?> RequestAsync(
Guid scheduleId,
string operationCode,
string scopeKey,
string automationMode,
string idempotencyKey,
string correlationId,
CancellationToken cancellationToken)
{
var definition = ModelOperationRegistry.GetRequired(operationCode);
ModelOperationExecutionBoundary.EnsureAllowed(definition);
if (!definition.AutomationMode.ToContractValue().Equals(automationMode, StringComparison.OrdinalIgnoreCase))
throw new InvalidOperationException("Schedule automation mode does not match the approved operation registry.");
var now = clock.UtcNow;
var context = await contextReader.ReadAsync(scopeKey, now, cancellationToken);
if (context is null)
return null;
context.VersionSet.EnsureValid();
var request = new ModelOperationRequest(
Guid.NewGuid(),
scheduleId,
definition.OperationCode,
scopeKey,
definition.AutomationMode.ToContractValue(),
idempotencyKey,
context,
correlationId,
now);
return await repository.AddAsync(request, cancellationToken) ? request : null;
}
}
@@ -0,0 +1,80 @@
using KArtSell.BuildingBlocks.Versioning;
namespace KArtSell.Modules.ModelOperations.Application;
public sealed record ApprovedModelContext(
string ScopeKey,
VersionSet VersionSet,
string LifecycleState,
DateTimeOffset EffectiveAt);
public sealed record DueModelOperation(
Guid ScheduleId,
string OperationCode,
string ScopeKey,
string Cadence,
string AutomationMode,
string Queue,
string IdempotencyKey,
int ScheduleVersion,
DateTimeOffset ScheduledFor,
string CatchUpPolicy,
int MaxCatchUp);
public sealed record ModelOperationRequest(
Guid RequestId,
Guid ScheduleId,
string OperationCode,
string ScopeKey,
string AutomationMode,
string IdempotencyKey,
ApprovedModelContext Context,
string CorrelationId,
DateTimeOffset RequestedAt);
public interface IApprovedModelContextReader
{
Task<ApprovedModelContext?> ReadAsync(string scopeKey, DateTimeOffset asOf, CancellationToken cancellationToken);
}
public interface IModelScheduleRepository
{
Task<IReadOnlyList<DueModelOperation>> AcquireDueAsync(
DateTimeOffset now,
string leaseOwner,
TimeSpan leaseDuration,
int limit,
CancellationToken cancellationToken);
Task MarkDispatchedAsync(
Guid scheduleId,
string leaseOwner,
string backgroundJobId,
DateTimeOffset dispatchedAt,
DateTimeOffset nextDueAt,
CancellationToken cancellationToken);
Task ReleaseAsync(
Guid scheduleId,
string leaseOwner,
string reasonCode,
DateTimeOffset releasedAt,
CancellationToken cancellationToken);
}
public interface IModelOperationRequestRepository
{
Task<bool> AddAsync(ModelOperationRequest request, CancellationToken cancellationToken);
}
public interface IModelOperationRequestService
{
Task<ModelOperationRequest?> RequestAsync(
Guid scheduleId,
string operationCode,
string scopeKey,
string automationMode,
string idempotencyKey,
string correlationId,
CancellationToken cancellationToken);
}