Rename Feedser to Concelier
This commit is contained in:
		@@ -0,0 +1,238 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.Extensions.Logging.Abstractions;
 | 
			
		||||
using Microsoft.Extensions.Options;
 | 
			
		||||
using MongoDB.Bson;
 | 
			
		||||
using MongoDB.Driver;
 | 
			
		||||
using StellaOps.Concelier.Storage.Mongo;
 | 
			
		||||
using StellaOps.Concelier.Storage.Mongo.Migrations;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace StellaOps.Concelier.Storage.Mongo.Tests.Migrations;
 | 
			
		||||
 | 
			
		||||
[Collection("mongo-fixture")]
 | 
			
		||||
public sealed class MongoMigrationRunnerTests
 | 
			
		||||
{
 | 
			
		||||
    private readonly MongoIntegrationFixture _fixture;
 | 
			
		||||
 | 
			
		||||
    public MongoMigrationRunnerTests(MongoIntegrationFixture fixture)
 | 
			
		||||
    {
 | 
			
		||||
        _fixture = fixture;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public async Task RunAsync_AppliesPendingMigrationsOnce()
 | 
			
		||||
    {
 | 
			
		||||
        var databaseName = $"concelier-migrations-{Guid.NewGuid():N}";
 | 
			
		||||
        var database = _fixture.Client.GetDatabase(databaseName);
 | 
			
		||||
        await database.CreateCollectionAsync(MongoStorageDefaults.Collections.Migrations);
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var migration = new TestMigration();
 | 
			
		||||
            var runner = new MongoMigrationRunner(
 | 
			
		||||
                database,
 | 
			
		||||
                new IMongoMigration[] { migration },
 | 
			
		||||
                NullLogger<MongoMigrationRunner>.Instance,
 | 
			
		||||
                TimeProvider.System);
 | 
			
		||||
 | 
			
		||||
            await runner.RunAsync(CancellationToken.None);
 | 
			
		||||
            await runner.RunAsync(CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
            Assert.Equal(1, migration.ApplyCount);
 | 
			
		||||
 | 
			
		||||
            var count = await database
 | 
			
		||||
                .GetCollection<BsonDocument>(MongoStorageDefaults.Collections.Migrations)
 | 
			
		||||
                .CountDocumentsAsync(FilterDefinition<BsonDocument>.Empty);
 | 
			
		||||
            Assert.Equal(1, count);
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            await _fixture.Client.DropDatabaseAsync(databaseName);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public async Task EnsureDocumentExpiryIndexesMigration_CreatesTtlIndexWhenRetentionEnabled()
 | 
			
		||||
    {
 | 
			
		||||
        var databaseName = $"concelier-doc-ttl-{Guid.NewGuid():N}";
 | 
			
		||||
        var database = _fixture.Client.GetDatabase(databaseName);
 | 
			
		||||
        await database.CreateCollectionAsync(MongoStorageDefaults.Collections.Document);
 | 
			
		||||
        await database.CreateCollectionAsync(MongoStorageDefaults.Collections.Migrations);
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var options = Options.Create(new MongoStorageOptions
 | 
			
		||||
            {
 | 
			
		||||
                RawDocumentRetention = TimeSpan.FromDays(45),
 | 
			
		||||
                RawDocumentRetentionTtlGrace = TimeSpan.FromHours(12),
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            var migration = new EnsureDocumentExpiryIndexesMigration(options);
 | 
			
		||||
            var runner = new MongoMigrationRunner(
 | 
			
		||||
                database,
 | 
			
		||||
                new IMongoMigration[] { migration },
 | 
			
		||||
                NullLogger<MongoMigrationRunner>.Instance,
 | 
			
		||||
                TimeProvider.System);
 | 
			
		||||
 | 
			
		||||
            await runner.RunAsync(CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
            var indexes = await database
 | 
			
		||||
                .GetCollection<BsonDocument>(MongoStorageDefaults.Collections.Document)
 | 
			
		||||
                .Indexes.ListAsync();
 | 
			
		||||
            var indexList = await indexes.ToListAsync();
 | 
			
		||||
 | 
			
		||||
            var ttlIndex = indexList.Single(x => x["name"].AsString == "document_expiresAt_ttl");
 | 
			
		||||
            Assert.Equal(0, ttlIndex["expireAfterSeconds"].ToDouble());
 | 
			
		||||
            Assert.True(ttlIndex["partialFilterExpression"].AsBsonDocument["expiresAt"].AsBsonDocument["$exists"].ToBoolean());
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            await _fixture.Client.DropDatabaseAsync(databaseName);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public async Task EnsureDocumentExpiryIndexesMigration_DropsTtlIndexWhenRetentionDisabled()
 | 
			
		||||
    {
 | 
			
		||||
        var databaseName = $"concelier-doc-notl-{Guid.NewGuid():N}";
 | 
			
		||||
        var database = _fixture.Client.GetDatabase(databaseName);
 | 
			
		||||
        await database.CreateCollectionAsync(MongoStorageDefaults.Collections.Document);
 | 
			
		||||
        await database.CreateCollectionAsync(MongoStorageDefaults.Collections.Migrations);
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var collection = database.GetCollection<BsonDocument>(MongoStorageDefaults.Collections.Document);
 | 
			
		||||
            var keys = Builders<BsonDocument>.IndexKeys.Ascending("expiresAt");
 | 
			
		||||
            var options = new CreateIndexOptions<BsonDocument>
 | 
			
		||||
            {
 | 
			
		||||
                Name = "document_expiresAt_ttl",
 | 
			
		||||
                ExpireAfter = TimeSpan.Zero,
 | 
			
		||||
                PartialFilterExpression = Builders<BsonDocument>.Filter.Exists("expiresAt", true),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            await collection.Indexes.CreateOneAsync(new CreateIndexModel<BsonDocument>(keys, options));
 | 
			
		||||
 | 
			
		||||
            var migration = new EnsureDocumentExpiryIndexesMigration(Options.Create(new MongoStorageOptions
 | 
			
		||||
            {
 | 
			
		||||
                RawDocumentRetention = TimeSpan.Zero,
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            var runner = new MongoMigrationRunner(
 | 
			
		||||
                database,
 | 
			
		||||
                new IMongoMigration[] { migration },
 | 
			
		||||
                NullLogger<MongoMigrationRunner>.Instance,
 | 
			
		||||
                TimeProvider.System);
 | 
			
		||||
 | 
			
		||||
            await runner.RunAsync(CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
            var indexes = await collection.Indexes.ListAsync();
 | 
			
		||||
            var indexList = await indexes.ToListAsync();
 | 
			
		||||
 | 
			
		||||
            Assert.DoesNotContain(indexList, x => x["name"].AsString == "document_expiresAt_ttl");
 | 
			
		||||
            var nonTtl = indexList.Single(x => x["name"].AsString == "document_expiresAt");
 | 
			
		||||
            Assert.False(nonTtl.Contains("expireAfterSeconds"));
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            await _fixture.Client.DropDatabaseAsync(databaseName);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public async Task EnsureGridFsExpiryIndexesMigration_CreatesTtlIndexWhenRetentionEnabled()
 | 
			
		||||
    {
 | 
			
		||||
        var databaseName = $"concelier-gridfs-ttl-{Guid.NewGuid():N}";
 | 
			
		||||
        var database = _fixture.Client.GetDatabase(databaseName);
 | 
			
		||||
        await database.CreateCollectionAsync("documents.files");
 | 
			
		||||
        await database.CreateCollectionAsync(MongoStorageDefaults.Collections.Migrations);
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var migration = new EnsureGridFsExpiryIndexesMigration(Options.Create(new MongoStorageOptions
 | 
			
		||||
            {
 | 
			
		||||
                RawDocumentRetention = TimeSpan.FromDays(30),
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            var runner = new MongoMigrationRunner(
 | 
			
		||||
                database,
 | 
			
		||||
                new IMongoMigration[] { migration },
 | 
			
		||||
                NullLogger<MongoMigrationRunner>.Instance,
 | 
			
		||||
                TimeProvider.System);
 | 
			
		||||
 | 
			
		||||
            await runner.RunAsync(CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
            var indexes = await database.GetCollection<BsonDocument>("documents.files").Indexes.ListAsync();
 | 
			
		||||
            var indexList = await indexes.ToListAsync();
 | 
			
		||||
 | 
			
		||||
            var ttlIndex = indexList.Single(x => x["name"].AsString == "gridfs_files_expiresAt_ttl");
 | 
			
		||||
            Assert.Equal(0, ttlIndex["expireAfterSeconds"].ToDouble());
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            await _fixture.Client.DropDatabaseAsync(databaseName);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public async Task EnsureGridFsExpiryIndexesMigration_DropsTtlIndexWhenRetentionDisabled()
 | 
			
		||||
    {
 | 
			
		||||
        var databaseName = $"concelier-gridfs-notl-{Guid.NewGuid():N}";
 | 
			
		||||
        var database = _fixture.Client.GetDatabase(databaseName);
 | 
			
		||||
        await database.CreateCollectionAsync("documents.files");
 | 
			
		||||
        await database.CreateCollectionAsync(MongoStorageDefaults.Collections.Migrations);
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var collection = database.GetCollection<BsonDocument>("documents.files");
 | 
			
		||||
            var keys = Builders<BsonDocument>.IndexKeys.Ascending("metadata.expiresAt");
 | 
			
		||||
            var options = new CreateIndexOptions<BsonDocument>
 | 
			
		||||
            {
 | 
			
		||||
                Name = "gridfs_files_expiresAt_ttl",
 | 
			
		||||
                ExpireAfter = TimeSpan.Zero,
 | 
			
		||||
                PartialFilterExpression = Builders<BsonDocument>.Filter.Exists("metadata.expiresAt", true),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            await collection.Indexes.CreateOneAsync(new CreateIndexModel<BsonDocument>(keys, options));
 | 
			
		||||
 | 
			
		||||
            var migration = new EnsureGridFsExpiryIndexesMigration(Options.Create(new MongoStorageOptions
 | 
			
		||||
            {
 | 
			
		||||
                RawDocumentRetention = TimeSpan.Zero,
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            var runner = new MongoMigrationRunner(
 | 
			
		||||
                database,
 | 
			
		||||
                new IMongoMigration[] { migration },
 | 
			
		||||
                NullLogger<MongoMigrationRunner>.Instance,
 | 
			
		||||
                TimeProvider.System);
 | 
			
		||||
 | 
			
		||||
            await runner.RunAsync(CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
            var indexes = await collection.Indexes.ListAsync();
 | 
			
		||||
            var indexList = await indexes.ToListAsync();
 | 
			
		||||
 | 
			
		||||
            Assert.DoesNotContain(indexList, x => x["name"].AsString == "gridfs_files_expiresAt_ttl");
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            await _fixture.Client.DropDatabaseAsync(databaseName);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private sealed class TestMigration : IMongoMigration
 | 
			
		||||
    {
 | 
			
		||||
        public int ApplyCount { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public string Id => "999_test";
 | 
			
		||||
 | 
			
		||||
        public string Description => "test migration";
 | 
			
		||||
 | 
			
		||||
        public Task ApplyAsync(IMongoDatabase database, CancellationToken cancellationToken)
 | 
			
		||||
        {
 | 
			
		||||
            ApplyCount++;
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user