// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Threading.Tasks; using Horde.Build.Jobs; using Horde.Build.Projects; using Horde.Build.Utilities; namespace Horde.Build.Streams { using JobId = ObjectId; using ProjectId = StringId; using StreamId = StringId; using TemplateId = StringId; /// /// Collection of stream documents /// public interface IStreamCollection { /// /// Creates or replaces a stream configuration /// /// Unique id for the new stream /// The current stream value. If not-null, this will attempt to replace the existing instance. /// The config file revision /// The project id /// Task TryCreateOrReplaceAsync(StreamId id, IStream? stream, string revision, ProjectId projectId); /// /// Gets a stream by ID /// /// Unique id of the stream /// The stream document Task GetAsync(StreamId streamId); /// /// Gets a stream's permissions by ID /// /// Unique id of the stream /// The stream document Task GetPermissionsAsync(StreamId streamId); /// /// Enumerates all streams /// /// Task> FindAllAsync(); /// /// Gets all the available streams for a project /// /// Unique id of the projects to query /// List of stream documents Task> FindForProjectsAsync(ProjectId[] projectIds); /// /// Updates user-facing properties for an existing stream /// /// The stream to update /// The new datetime for pausing builds /// The reason for pausing /// The updated stream if successful, null otherwise Task TryUpdatePauseStateAsync(IStream stream, DateTime? newPausedUntil, string? newPauseComment); /// /// Attempts to update the last trigger time for a schedule /// /// The stream to update /// The template ref id /// New last trigger time for the schedule /// New last trigger changelist for the schedule /// New list of active jobs /// The updated stream if successful, null otherwise Task TryUpdateScheduleTriggerAsync(IStream stream, TemplateId templateRefId, DateTime? lastTriggerTimeUtc, int? lastTriggerChange, List newActiveJobs); /// /// Attempts to update a stream template ref /// /// The stream containing the template ref /// The template ref to update /// The stream states to update, pass an empty list to clear all step states, otherwise will be a partial update based on included step updates /// Task TryUpdateTemplateRefAsync(IStream streamInterface, TemplateId templateRefId, List? stepStates = null); /// /// Delete a stream /// /// Unique id of the stream /// Async task Task DeleteAsync(StreamId streamId); } static class StreamCollectionExtensions { /// /// Creates or replaces a stream configuration /// /// The stream collection /// Unique id for the new stream /// The current stream value. If not-null, this will attempt to replace the existing instance. /// The config file revision /// The project id /// public static async Task CreateOrReplaceAsync(this IStreamCollection streamCollection, StreamId id, IStream? stream, string revision, ProjectId projectId) { for (; ; ) { stream = await streamCollection.TryCreateOrReplaceAsync(id, stream, revision, projectId); if (stream != null) { return stream; } stream = await streamCollection.GetAsync(id); } } } }