Open Closed

An exception was thrown while activating CprOnAbp.MemberConfigService.DbMigrations.MemberConfigServiceDatabaseMigrationEventHandler #7717


User avatar
0
rogercprops created
  • ABP Framework version: v7.2.2 Commercial
  • UI Type: AN/A
  • Database System: MongoDB
  • Tiered (for MVC) or Auth Server Separated (for Angular): yes
  • Exception message and full stack trace: We have a microservice solution built with the Microservice Template and have a MemberConfigService microservice.
    We modified the CprOnAbp.Shared.Hosting.Microservices/DbMigrations to add MongoDBMigrationEventHandlerBase, PendingMongoDbMigrationsChecker and PendingMongoDBMigrationsCheckerBase classes to handle MongoDb. However these haven't been modified since March.

I made some changes to the MemberConfigService, tested the service on localhost successfully but when I deploy to Kubernetes I get the following error that's just running in an infinite loop until I kill the pod. I deployed the previous image that was running in in AKS and it too is getting he same error.

 An exception was thrown while activating CprOnAbp.MemberConfigService.DbMigrations.MemberConfigServiceDatabaseMigrationEventHandler.
Autofac.Core.DependencyResolutionException: An exception was thrown while activating CprOnAbp.MemberConfigService.DbMigrations.MemberConfigServiceDatabaseMigrationEventHandler.
 ---> Autofac.Core.DependencyResolutionException: None of the constructors found on type 'CprOnAbp.MemberConfigService.DbMigrations.MemberConfigServiceDatabaseMigrationEventHandler' can be invoked with the available services and parameters:
Cannot resolve parameter 'System.String databaseName' of constructor 'Void .ctor(Volo.Abp.MultiTenancy.ICurrentTenant, Volo.Abp.Uow.IUnitOfWorkManager, Volo.Abp.MultiTenancy.ITenantStore, Volo.Saas.Tenants.ITenantRepository, Volo.Abp.EventBus.Distributed.IDistributedEventBus, System.String, System.IServiceProvider)'.
See https://autofac.rtfd.io/help/no-constructors-bindable for more info.
   at Autofac.Core.Activators.Reflection.ReflectionActivator.<>c__DisplayClass14_0.<UseSingleConstructorActivation>b__0(ResolveRequestContext ctxt, Action`1 next)
   at Autofac.Core.Resolving.Middleware.DelegateMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.DisposalTrackingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.&lt;&gt;c__DisplayClass14_0.&lt;BuildPipeline&gt;b__1(ResolveRequestContext ctxt)
   at Autofac.Builder.RegistrationBuilder`3.<>c__DisplayClass41_0.<PropertiesAutowired>b__0(ResolveRequestContext ctxt, Action`1 next)
   at Autofac.Core.Resolving.Middleware.DelegateMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   --- End of inner exception stack trace ---
   at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Pipeline.ResolvePipeline.Invoke(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.RegistrationPipelineInvokeMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.&lt;&gt;c__DisplayClass14_0.&lt;BuildPipeline&gt;b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.&lt;&gt;c__DisplayClass14_0.&lt;BuildPipeline&gt;b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Pipeline.ResolvePipeline.Invoke(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request)
   at Autofac.Core.Resolving.ResolveOperation.ExecuteOperation(ResolveRequest request)
   at Autofac.Core.Resolving.ResolveOperation.Execute(ResolveRequest request)
   at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(ResolveRequest request)
   at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
   at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType)
   at Autofac.Extensions.DependencyInjection.AutofacServiceProvider.GetRequiredService(Type serviceType)
   at Volo.Abp.EventBus.IocEventHandlerFactory.GetHandler()
   at Volo.Abp.EventBus.EventBusBase.TriggerHandlerAsync(IEventHandlerFactory asyncHandlerFactory, Type eventType, Object eventData, List`1 exceptions, InboxConfig inboxConfig)
   at Volo.Abp.EventBus.EventBusBase.TriggerHandlersAsync(Type eventType, Object eventData, List`1 exceptions, InboxConfig inboxConfig)
   at Volo.Abp.EventBus.EventBusBase.TriggerHandlersAsync(Type eventType, Object eventData)
   at Volo.Abp.EventBus.RabbitMq.RabbitMqDistributedEventBus.ProcessEventAsync(IModel channel, BasicDeliverEventArgs ea)
   at Volo.Abp.RabbitMQ.RabbitMqMessageConsumer.HandleIncomingMessageAsync(Object sender, BasicDeliverEventArgs basicDeliverEventArgs)
[20:56:07 ERR] ---------- Exception Data ----------
ActivatorChain = CprOnAbp.MemberConfigService.DbMigrations.MemberConfigServiceDatabaseMigrationEventHandler
  • Steps to reproduce the issue:
    1. Created docker image
    2. Uploaded the image to Azure container registry
    3. Updated the deployment manifest
    4. Deployed updated manifest (kubectl apply -f ....)

I can give whoever access to our GitHub repository if necessary.


7 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you share your code of MongoDBMigrationEventHandlerBase, PendingMongoDbMigrationsChecker and PendingMongoDBMigrationsCheckerBase ?

    and you can check the https://github.com/abpframework/abp/issues/17946#issuecomment-1782180774

  • User Avatar
    0
    rogercprops created

    Hi,

    I looked at the GitHub issue and it doesn't seem to apply. I'm not having an issue with seeding the database and I can't find RuntimeDatabaseMigrator anywhere.

    Here are the 3 classes
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Threading.Tasks;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Logging.Abstractions;
    using MongoDB.Driver;
    using Volo.Abp;
    using Volo.Abp.Data;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.Domain.Entities.Events.Distributed;
    using Volo.Abp.EventBus.Distributed;
    using Volo.Abp.MongoDB;
    using Volo.Abp.MultiTenancy;
    using Volo.Abp.Uow;
    using Volo.Saas.Tenants;
    
    namespace CprOnAbp.Shared.Hosting.Microservices.DbMigrations.MongoDb;
    
    public abstract class MongoDBMigrationEventHandlerBase<TDbContext> :
            ITransientDependency
            where TDbContext : AbpMongoDbContext, IAbpMongoDbContext
    {
        protected const string TryCountPropertyName = "TryCount";
        protected const int MaxEventTryCount = 3;
    
        protected ICurrentTenant CurrentTenant { get; }
        protected IUnitOfWorkManager UnitOfWorkManager { get; }
        protected ITenantStore TenantStore { get; }
        protected ITenantRepository TenantRepository { get; }
        protected IDistributedEventBus DistributedEventBus { get; }
        protected ILogger<MongoDBMigrationEventHandlerBase<TDbContext>> Logger { get; set; }
    
        protected IServiceProvider ServiceProvider { get; }
        protected string DatabaseName { get; }
    
        protected MongoDBMigrationEventHandlerBase(
            ICurrentTenant currentTenant,
            IUnitOfWorkManager unitOfWorkManager,
            ITenantStore tenantStore,
            ITenantRepository tenantRepository,
            IDistributedEventBus distributedEventBus,
            string databaseName, IServiceProvider serviceProvider)
        {
            CurrentTenant = currentTenant;
            UnitOfWorkManager = unitOfWorkManager;
            TenantStore = tenantStore;
            DatabaseName = databaseName;
            ServiceProvider = serviceProvider;
            DistributedEventBus = distributedEventBus;
            TenantRepository = tenantRepository;
    
            Logger = NullLogger<MongoDBMigrationEventHandlerBase<TDbContext>>.Instance;
        }
    
        /// <summary>
        /// Apply pending EF Core schema migrations to the database.
        /// Returns true if any migration has applied.
        /// </summary>
        protected virtual async Task<bool> MigrateDatabaseSchemaAsync(Guid? tenantId)
        {
            var result = false;
    
            using (CurrentTenant.Change(tenantId))
            {
                using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false))
                {
                    async Task<bool> MigrateDatabaseSchemaWithDbContextAsync()
                    {
                        var dbContexts = ServiceProvider.GetServices<IAbpMongoDbContext>();
                        var connectionStringResolver = ServiceProvider.GetRequiredService<IConnectionStringResolver>();
    
                        if (ServiceProvider.GetRequiredService<ICurrentTenant>().IsAvailable)
                        {
                            dbContexts = dbContexts.Where(x =>
                                !x.GetType().IsDefined(typeof(IgnoreMultiTenancyAttribute)));
                        }
    
                        foreach (var dbContext in dbContexts)
                        {
                            var connectionString =
                                await connectionStringResolver.ResolveAsync(
                                    ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType()));
                            if (connectionString.IsNullOrWhiteSpace())
                            {
                                continue;
                            }
                            var mongoUrl = new MongoUrl(connectionString);
                            var databaseName = mongoUrl.DatabaseName;
                            var client = new MongoClient(mongoUrl);
    
                            if (databaseName.IsNullOrWhiteSpace())
                            {
                                databaseName = ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType());
                            }
    
                            (dbContext as AbpMongoDbContext)?.InitializeCollections(client.GetDatabase(databaseName));
                        }
    
                        return true;
                    }
    
                    if (tenantId == null)
                    {
                        //Migrating the host database
                        result = await MigrateDatabaseSchemaWithDbContextAsync();
                    }
                    else
                    {
                        var tenantConfiguration = await TenantStore.FindAsync(tenantId.Value);
                        if (!tenantConfiguration.ConnectionStrings.Default.IsNullOrWhiteSpace() ||
                            !tenantConfiguration.ConnectionStrings.GetOrDefault(DatabaseName).IsNullOrWhiteSpace())
                        {
                            //Migrating the tenant database (only if tenant has a separate database)
                            result = await MigrateDatabaseSchemaWithDbContextAsync();
                        }
                    }
    
                    await uow.CompleteAsync();
                }
            }
    
            return result;
        }
    
        protected virtual async Task HandleErrorOnApplyDatabaseMigrationAsync(
            ApplyDatabaseMigrationsEto eventData,
            Exception exception)
        {
            var tryCount = IncrementEventTryCount(eventData);
            if (tryCount <= MaxEventTryCount)
            {
                Logger.LogWarning(
                    $"Could not apply database migrations. Re-queueing the operation. TenantId = {eventData.TenantId}, Database Name = {eventData.DatabaseName}.");
                Logger.LogException(exception, LogLevel.Warning);
    
                await Task.Delay(RandomHelper.GetRandom(5000, 15000));
                await DistributedEventBus.PublishAsync(eventData);
            }
            else
            {
                Logger.LogError(
                    $"Could not apply database migrations. Canceling the operation. TenantId = {eventData.TenantId}, DatabaseName = {eventData.DatabaseName}.");
                Logger.LogException(exception);
            }
        }
    
        protected virtual async Task HandleErrorTenantCreatedAsync(
            TenantCreatedEto eventData,
            Exception exception)
        {
            var tryCount = IncrementEventTryCount(eventData);
            if (tryCount <= MaxEventTryCount)
            {
                Logger.LogWarning(
                    $"Could not perform tenant created event. Re-queueing the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}.");
                Logger.LogException(exception, LogLevel.Warning);
    
                await Task.Delay(RandomHelper.GetRandom(5000, 15000));
                await DistributedEventBus.PublishAsync(eventData);
            }
            else
            {
                Logger.LogError(
                    $"Could not perform tenant created event. Canceling the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}.");
                Logger.LogException(exception);
            }
        }
    
        protected virtual async Task HandleErrorTenantConnectionStringUpdatedAsync(
            TenantConnectionStringUpdatedEto eventData,
            Exception exception)
        {
            var tryCount = IncrementEventTryCount(eventData);
            if (tryCount <= MaxEventTryCount)
            {
                Logger.LogWarning(
                    $"Could not perform tenant connection string updated event. Re-queueing the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}.");
                Logger.LogException(exception, LogLevel.Warning);
    
                await Task.Delay(RandomHelper.GetRandom(5000, 15000));
                await DistributedEventBus.PublishAsync(eventData);
            }
            else
            {
                Logger.LogError(
                    $"Could not perform tenant connection string updated event. Canceling the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}.");
                Logger.LogException(exception);
            }
        }
    
        protected virtual async Task QueueTenantMigrationsAsync()
        {
            var tenants = await TenantRepository.GetListWithSeparateConnectionStringAsync();
            foreach (var tenant in tenants)
            {
                await DistributedEventBus.PublishAsync(
                    new ApplyDatabaseMigrationsEto
                    {
                        DatabaseName = DatabaseName,
                        TenantId = tenant.Id
                    }
                );
            }
        }
    
        private static int GetEventTryCount(EtoBase eventData)
        {
            var tryCountAsString = eventData.Properties.GetOrDefault(TryCountPropertyName);
            if (tryCountAsString.IsNullOrEmpty())
            {
                return 0;
            }
    
            return int.Parse(tryCountAsString);
        }
    
        private static void SetEventTryCount(EtoBase eventData, int count)
        {
            eventData.Properties[TryCountPropertyName] = count.ToString();
        }
    
        private static int IncrementEventTryCount(EtoBase eventData)
        {
            var count = GetEventTryCount(eventData) + 1;
            SetEventTryCount(eventData, count);
            return count;
        }
    }
    public abstract class PendingMongoDbMigrationsChecker<TDbContext> : PendingMigrationsCheckerBase where TDbContext : AbpMongoDbContext
    {
        protected IUnitOfWorkManager UnitOfWorkManager { get; }
        protected IServiceProvider ServiceProvider { get; }
        protected ICurrentTenant CurrentTenant { get; }
        protected IDistributedEventBus DistributedEventBus { get; }
        protected IAbpDistributedLock DistributedLockProvider { get; }
        protected string DatabaseName { get; }
        protected IDataSeeder DataSeeder { get; }
        
        protected PendingMongoDbMigrationsChecker(
            ILoggerFactory loggerFactory,
            IUnitOfWorkManager unitOfWorkManager,
            IServiceProvider serviceProvider,
            ICurrentTenant currentTenant,
            IDistributedEventBus distributedEventBus,
            IAbpDistributedLock abpDistributedLock,
            string databaseName, 
            IDataSeeder dataSeeder) : base(loggerFactory)
        {
            UnitOfWorkManager = unitOfWorkManager;
            ServiceProvider = serviceProvider;
            CurrentTenant = currentTenant;
            DistributedEventBus = distributedEventBus;
            DistributedLockProvider = abpDistributedLock;
            DatabaseName = databaseName;
            DataSeeder = dataSeeder;
        }
        
        public virtual async Task CheckAndApplyDatabaseMigrationsAsync()
        {
            await TryAsync(async () =>
            {
                using (CurrentTenant.Change(null))
                {
                    // Create database tables if needed
                    using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false))
                    {
                        await MigrateDatabaseSchemaAsync();
    
                        await DataSeeder.SeedAsync();
    
                        await uow.CompleteAsync();
                    }
                }
            });
        }
        /// <summary>
        /// Apply scheme update for MongoDB Database.
        /// </summary>
        protected virtual async Task<bool> MigrateDatabaseSchemaAsync()
        {
            var result = false;
            await using (var handle = await DistributedLockProvider.TryAcquireAsync("Migration_" + DatabaseName))
            {
                using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false))
                {
                    Log.Information($"Lock is acquired for db migration and seeding on database named: {DatabaseName}...");
    
                    if (handle is null)
                    {
                        Log.Information($"Handle is null because of the locking for : {DatabaseName}");
                        return false;
                    }
    
                    async Task<bool> MigrateDatabaseSchemaWithDbContextAsync()
                    {
                        var dbContexts = ServiceProvider.GetServices<IAbpMongoDbContext>();
                        var connectionStringResolver = ServiceProvider.GetRequiredService<IConnectionStringResolver>();
    
                        foreach (var dbContext in dbContexts)
                        {
                            var connectionString =
                                await connectionStringResolver.ResolveAsync(
                                    ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType()));
                            if (connectionString.IsNullOrWhiteSpace())
                            {
                                continue;
                            }
    
                            var mongoUrl = new MongoUrl(connectionString);
                            var databaseName = mongoUrl.DatabaseName;
                            var client = new MongoClient(mongoUrl);
    
                            if (databaseName.IsNullOrWhiteSpace())
                            {
                                databaseName = ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType());
                            }
    
                            (dbContext as AbpMongoDbContext)?.InitializeCollections(client.GetDatabase(databaseName));
                        }
    
                        return true;
                    }
    
                    //Migrating the host database
                    result = await MigrateDatabaseSchemaWithDbContextAsync();
    
                    await uow.CompleteAsync();
                }
    
                return result;
            }
        }
    }
    using System;
    using System.Threading.Tasks;
    using Volo.Abp.Data;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.EventBus.Distributed;
    using Volo.Abp.MongoDB;
    using Volo.Abp.MultiTenancy;
    using Volo.Abp.Uow;
    
    namespace CprOnAbp.Shared.Hosting.Microservices.DbMigrations.MongoDb;
    
    public class PendingMongoDBMigrationsCheckerBase<TDbContext> : ITransientDependency
            where TDbContext : AbpMongoDbContext
    {
        protected IUnitOfWorkManager UnitOfWorkManager { get; }
        protected IServiceProvider ServiceProvider { get; }
        protected ICurrentTenant CurrentTenant { get; }
        protected IDistributedEventBus DistributedEventBus { get; }
        protected string DatabaseName { get; }
    
        protected PendingMongoDBMigrationsCheckerBase(
            IUnitOfWorkManager unitOfWorkManager,
            IServiceProvider serviceProvider,
            ICurrentTenant currentTenant,
            IDistributedEventBus distributedEventBus,
            string databaseName)
        {
            UnitOfWorkManager = unitOfWorkManager;
            ServiceProvider = serviceProvider;
            CurrentTenant = currentTenant;
            DistributedEventBus = distributedEventBus;
            DatabaseName = databaseName;
        }
    
        public virtual async Task CheckAsync()
        {
            using (CurrentTenant.Change(null))
            {
                // Create database tables if needed
                using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false))
                {
                    await DistributedEventBus.PublishAsync(
                            new ApplyDatabaseMigrationsEto
                            {
                                DatabaseName = DatabaseName
                            }
                        );
    
                    await uow.CompleteAsync();
                }
            }
        }
    }
    
  • User Avatar
    0
    rogercprops created

    Another piece of information. I applied the same docker image to our production AKS cluster and it's running fine.

    So it's clearly an issue running in AKS. Could there be something in cache or some other AKS condition that's causing the microservice error?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please share the code for MongoDBMigrationEventHandlerBase PendingMongoDbMigrationsChecker, PendingMongoDBMigrationsCheckerBase sub-classes

  • User Avatar
    0
    rogercprops created

    Hi,

    I sent you an invite to our microservices shared repository and member-config-service repositories.

    The classes you requested are in the shared/CprOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb folder.

    Please let me know if you need anything else.

    Thanks

  • User Avatar
    0
    rogercprops created

    Hi again,

    One more thing. This might be a kubernetes issue. I noticed our AKS cluster was at 75% memory utilization so I deleted all of the applications and then re-deployed them.

    The member-config-service is running without error.

    Could there be a memory leak in the application? And could a lack of available memory be causing this error and just not catching it so that it shows that error message?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    You can try a deploy project to k8s to see if the same problem exists, I don't have much experience with k8s.

    Can you share the application Logs.txt?

    Maybe it has some other error messages.

    Set log level to Debug

    public class Program
    {
        public async static Task<int> Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
                .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
                .Enrich.FromLogContext()
                .WriteTo.Async(c => c.File("Logs/logs.txt"))
                .WriteTo.Async(c => c.Console())
                .CreateLogger();
    
Made with ❤️ on ABP v9.1.0-preview. Updated on November 11, 2024, 11:11