feat(ai): centralize durable usage
Add a content-free usage ledger with legacy backfill. Reserve Workspace and durable Strategy/CV work before execution so deleted history or duplicate admission cannot reset limits.
This commit is contained in:
@@ -100,6 +100,10 @@ public sealed class SqliteDateTimeOffsetCompatibilityTests
|
||||
Interaction("user-1", job.Id, now),
|
||||
Interaction("user-1", job.Id, now.AddMonths(-2)),
|
||||
Interaction("user-2", job.Id, now));
|
||||
db.AiUsageRecords.AddRange(
|
||||
Usage("user-1", "current", now),
|
||||
Usage("user-1", "old", now.AddMonths(-2)),
|
||||
Usage("user-2", "other", now));
|
||||
db.CvExtractionRuns.AddRange(
|
||||
Run("user-1", now.AddDays(-1), "old"),
|
||||
Run("user-1", now, "new"),
|
||||
@@ -116,6 +120,7 @@ public sealed class SqliteDateTimeOffsetCompatibilityTests
|
||||
var generate = await new AiWorkspaceController(users.Object, workspaceService.Object, new ConfigurationBuilder().Build(), db)
|
||||
.Generate(job.Id, new AiWorkspaceController.GenerateRequest("job-analysis", null, null), default);
|
||||
Assert.IsType<NotFoundResult>(generate.Result);
|
||||
Assert.Equal(2, await db.AiUsageRecords.CountAsync());
|
||||
|
||||
var newestArtifactPath = Path.Combine(fixture.Paths.CvArtifactsRoot, "new.txt");
|
||||
await File.WriteAllTextAsync(newestArtifactPath, "synthetic CV");
|
||||
@@ -146,6 +151,19 @@ public sealed class SqliteDateTimeOffsetCompatibilityTests
|
||||
UpdatedAtUtc = updated,
|
||||
};
|
||||
|
||||
private static AiUsageRecord Usage(string owner, string sourceId, DateTimeOffset created) => new()
|
||||
{
|
||||
OwnerUserId = owner,
|
||||
SourceType = "test",
|
||||
SourceId = sourceId,
|
||||
TaskType = "workspace.test",
|
||||
CallCount = 1,
|
||||
InputCharacterCount = 10,
|
||||
OutputCharacterCount = 5,
|
||||
EstimatedTokenCount = 4,
|
||||
CreatedAtUtc = created,
|
||||
};
|
||||
|
||||
private static AiInteraction Interaction(string owner, int jobId, DateTimeOffset created) => new()
|
||||
{
|
||||
OwnerUserId = owner,
|
||||
|
||||
Reference in New Issue
Block a user