📄 src/Domain/Uploader.cs
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using Microsoft.Extensions.DependencyInjection;

namespace Slopper.Domain;

public sealed class Uploader(IServiceProvider serviceProvider, IClipRepository clipRepository)
{
    public async IAsyncEnumerable<Upload> Upload(
        string platform,
        [EnumeratorCancellation] CancellationToken cancellationToken
    )
    {
        var uploader = serviceProvider.GetRequiredKeyedService<IUploader>(platform);

        await foreach (var clip in clipRepository.GetNotUploadedTo(platform, cancellationToken))
        {
            var upload = await uploader.Upload(clip, cancellationToken);
            clip.Uploads.Add(upload);
            await clipRepository.Save(clip, cancellationToken);

            yield return upload;
        }
    }
}

public static class UploaderServiceCollectionExtensions
{
    extension(IServiceCollection services)
    {
        public IServiceCollection AddUploader()
        {
            services.AddTransient<Uploader>();
            return services;
        }
    }
}