159 lines
6.5 KiB
Transact-SQL
159 lines
6.5 KiB
Transact-SQL
CREATE OR ALTER PROCEDURE dbo.StoryIntelligenceRun_ClaimNextPendingFair
|
|
@MaxConcurrentRunsPerBook int = 2,
|
|
@MaxConcurrentRunsPerUser int = 3,
|
|
@ClaimLeaseMinutes int = 90
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
SET XACT_ABORT ON;
|
|
|
|
DECLARE @Now datetime2(7) = SYSUTCDATETIME();
|
|
DECLARE @SafeMaxPerBook int = CASE WHEN ISNULL(@MaxConcurrentRunsPerBook, 0) < 1 THEN 1 ELSE @MaxConcurrentRunsPerBook END;
|
|
DECLARE @SafeMaxPerUser int = CASE WHEN ISNULL(@MaxConcurrentRunsPerUser, 0) < 1 THEN 1 ELSE @MaxConcurrentRunsPerUser END;
|
|
DECLARE @SafeClaimLeaseMinutes int = CASE WHEN ISNULL(@ClaimLeaseMinutes, 0) < 15 THEN 15 ELSE @ClaimLeaseMinutes END;
|
|
DECLARE @StoryIntelligenceRunID int;
|
|
|
|
BEGIN TRANSACTION;
|
|
|
|
UPDATE dbo.StoryIntelligenceRuns
|
|
SET Status = N'Pending',
|
|
CurrentStage = N'Pending',
|
|
CurrentMessage = N'Returned to the Story Intelligence queue after an expired worker claim.',
|
|
StartedUtc = NULL,
|
|
UpdatedUtc = @Now
|
|
WHERE Status = N'Running'
|
|
AND CancellationRequestedUtc IS NULL
|
|
AND UpdatedUtc < DATEADD(minute, -@SafeClaimLeaseMinutes, @Now);
|
|
|
|
;WITH PendingRuns AS
|
|
(
|
|
SELECT
|
|
pending.StoryIntelligenceRunID,
|
|
pending.CreatedUtc,
|
|
pending.UserID,
|
|
pending.BookID,
|
|
ActiveForBook = (
|
|
SELECT COUNT_BIG(1)
|
|
FROM dbo.StoryIntelligenceRuns activeBook
|
|
WHERE activeBook.Status = N'Running'
|
|
AND activeBook.BookID = pending.BookID
|
|
),
|
|
ActiveForUser = (
|
|
SELECT COUNT_BIG(1)
|
|
FROM dbo.StoryIntelligenceRuns activeUser
|
|
WHERE activeUser.Status = N'Running'
|
|
AND activeUser.UserID = pending.UserID
|
|
)
|
|
FROM dbo.StoryIntelligenceRuns pending WITH (UPDLOCK, READPAST)
|
|
WHERE pending.Status = N'Pending'
|
|
AND (
|
|
pending.BookID IS NULL
|
|
OR (
|
|
SELECT COUNT_BIG(1)
|
|
FROM dbo.StoryIntelligenceRuns activeBook
|
|
WHERE activeBook.Status = N'Running'
|
|
AND activeBook.BookID = pending.BookID
|
|
) < @SafeMaxPerBook
|
|
)
|
|
AND (
|
|
SELECT COUNT_BIG(1)
|
|
FROM dbo.StoryIntelligenceRuns activeUser
|
|
WHERE activeUser.Status = N'Running'
|
|
AND activeUser.UserID = pending.UserID
|
|
) < @SafeMaxPerUser
|
|
)
|
|
SELECT TOP (1) @StoryIntelligenceRunID = StoryIntelligenceRunID
|
|
FROM PendingRuns
|
|
ORDER BY
|
|
ActiveForBook,
|
|
ActiveForUser,
|
|
CreatedUtc,
|
|
StoryIntelligenceRunID;
|
|
|
|
IF @StoryIntelligenceRunID IS NOT NULL
|
|
BEGIN
|
|
UPDATE dbo.StoryIntelligenceRuns
|
|
SET Status = N'Running',
|
|
StartedUtc = @Now,
|
|
CurrentStage = N'ChapterStructure',
|
|
CurrentMessage = N'Running Chapter Structure analysis.',
|
|
UpdatedUtc = @Now
|
|
WHERE StoryIntelligenceRunID = @StoryIntelligenceRunID
|
|
AND Status = N'Pending';
|
|
END;
|
|
|
|
COMMIT TRANSACTION;
|
|
|
|
IF @StoryIntelligenceRunID IS NULL
|
|
BEGIN
|
|
SELECT TOP (0)
|
|
StoryIntelligenceRunID, UserID, ProjectID, BookID, ChapterID, ChapterNumber, Status, SourceType, SourceLabel,
|
|
SourceText, SourceWordCount, SourceCharacterCount, SourceParagraphCount, SourceChapterCount, PromptVersion,
|
|
PromptVersionsSummary, KnownCharactersJson, Model, StartedUtc, CompletedUtc, FailureStage, TotalInputTokens,
|
|
TotalOutputTokens, TotalTokens, TotalDurationMs, EstimatedCostGBP, EstimatedCostUSD,
|
|
ErrorMessage, ErrorDetail, CurrentStage, CurrentMessage, TotalDetectedScenes,
|
|
CompletedScenes, FailedScenes, CancellationRequestedUtc, CancelledUtc, CreatedUtc, UpdatedUtc
|
|
FROM dbo.StoryIntelligenceRuns;
|
|
RETURN;
|
|
END;
|
|
|
|
SELECT
|
|
StoryIntelligenceRunID, UserID, ProjectID, BookID, ChapterID, ChapterNumber, Status, SourceType, SourceLabel,
|
|
SourceText, SourceWordCount, SourceCharacterCount, SourceParagraphCount, SourceChapterCount, PromptVersion,
|
|
PromptVersionsSummary, KnownCharactersJson, Model, StartedUtc, CompletedUtc, FailureStage, TotalInputTokens,
|
|
TotalOutputTokens, TotalTokens, TotalDurationMs, EstimatedCostGBP, EstimatedCostUSD,
|
|
ErrorMessage, ErrorDetail, CurrentStage, CurrentMessage, TotalDetectedScenes,
|
|
CompletedScenes, FailedScenes, CancellationRequestedUtc, CancelledUtc, CreatedUtc, UpdatedUtc
|
|
FROM dbo.StoryIntelligenceRuns
|
|
WHERE StoryIntelligenceRunID = @StoryIntelligenceRunID;
|
|
END;
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.StoryIntelligenceRun_ListActiveBookSummaryForUser
|
|
@UserID int
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
SELECT
|
|
r.UserID,
|
|
r.ProjectID,
|
|
p.ProjectName AS ProjectTitle,
|
|
r.BookID,
|
|
b.BookTitle,
|
|
b.Subtitle AS BookSubtitle,
|
|
COUNT(1) AS RunCount,
|
|
SUM(CASE WHEN r.Status = N'Pending' THEN 1 ELSE 0 END) AS PendingRunCount,
|
|
SUM(CASE WHEN r.Status = N'Running' THEN 1 ELSE 0 END) AS RunningRunCount,
|
|
SUM(CASE WHEN r.Status IN (N'Completed', N'CompletedWithWarnings') THEN 1 ELSE 0 END) AS CompletedRunCount,
|
|
SUM(CASE WHEN r.Status IN (N'Failed', N'Cancelled') THEN 1 ELSE 0 END) AS FailedRunCount,
|
|
SUM(ISNULL(r.TotalDetectedScenes, 0)) AS TotalDetectedScenes,
|
|
SUM(ISNULL(r.CompletedScenes, 0)) AS CompletedScenes,
|
|
SUM(ISNULL(r.FailedScenes, 0)) AS FailedScenes,
|
|
SUM(ISNULL(r.TotalDurationMs, 0)) AS TotalDurationMs,
|
|
MIN(r.CreatedUtc) AS FirstCreatedUtc,
|
|
MAX(r.UpdatedUtc) AS UpdatedUtc
|
|
FROM dbo.StoryIntelligenceRuns r
|
|
LEFT JOIN dbo.Projects p ON p.ProjectID = r.ProjectID
|
|
LEFT JOIN dbo.Books b ON b.BookID = r.BookID
|
|
WHERE r.UserID = @UserID
|
|
AND r.Status IN (N'Pending', N'Running')
|
|
GROUP BY r.UserID, r.ProjectID, p.ProjectName, r.BookID, b.BookTitle, b.Subtitle
|
|
ORDER BY MAX(r.UpdatedUtc) DESC, MIN(r.CreatedUtc);
|
|
END;
|
|
GO
|
|
|
|
IF NOT EXISTS
|
|
(
|
|
SELECT 1
|
|
FROM sys.indexes
|
|
WHERE name = N'IX_StoryIntelligenceRuns_QueueFairness'
|
|
AND object_id = OBJECT_ID(N'dbo.StoryIntelligenceRuns')
|
|
)
|
|
BEGIN
|
|
CREATE INDEX IX_StoryIntelligenceRuns_QueueFairness
|
|
ON dbo.StoryIntelligenceRuns (Status, UserID, BookID, CreatedUtc, StoryIntelligenceRunID)
|
|
INCLUDE (ProjectID, ChapterID, ChapterNumber, UpdatedUtc, TotalDetectedScenes, CompletedScenes, FailedScenes, TotalDurationMs);
|
|
END;
|
|
GO
|