Esempio n. 1
0
        public async Task UpdateAsync(string featureId)
        {
            if (_processedFeatures.Contains(featureId))
            {
                return;
            }

            _processedFeatures.Add(featureId);

            if (_logger.IsEnabled(LogLevel.Information))
            {
                _logger.LogInformation("Updating feature: {0}", featureId);
            }

            // proceed with dependent features first, whatever the module it's in
            var dependencies = _extensionManager
                               .GetDependentFeatures(
                featureId)
                               .Where(x => x.Id != featureId)
                               .Select(x => x.Id);

            await UpdateAsync(dependencies);

            var migrations = GetDataMigrations(featureId);

            // apply update methods to each migration class for the module
            foreach (var migration in migrations)
            {
                var schemaBuilder = new SchemaBuilder(_session);
                migration.SchemaBuilder = schemaBuilder;

                // copy the object for the Linq query
                var tempMigration = migration;

                // get current version for this migration
                var dataMigrationRecord = GetDataMigrationRecordAsync(tempMigration).Result;

                var current = 0;
                if (dataMigrationRecord != null)
                {
                    current = dataMigrationRecord.Version.Value;
                }
                else
                {
                    dataMigrationRecord = new Records.DataMigration {
                        DataMigrationClass = migration.GetType().FullName
                    };
                    _dataMigrationRecord.DataMigrations.Add(dataMigrationRecord);
                }

                try
                {
                    // do we need to call Create() ?
                    if (current == 0)
                    {
                        // try to resolve a Create method

                        var createMethod = GetCreateMethod(migration);
                        if (createMethod != null)
                        {
                            current = (int)createMethod.Invoke(migration, new object[0]);
                        }
                    }

                    var lookupTable = CreateUpgradeLookupTable(migration);

                    while (lookupTable.ContainsKey(current))
                    {
                        try
                        {
                            if (_logger.IsEnabled(LogLevel.Information))
                            {
                                _logger.LogInformation("Applying migration for {0} from version {1}.", featureId, current);
                            }
                            current = (int)lookupTable[current].Invoke(migration, new object[0]);
                        }
                        catch (Exception ex)
                        {
                            if (ex.IsFatal())
                            {
                                throw;
                            }
                            _logger.LogError(0, "An unexpected error occurred while applying migration on {0} from version {1}.", featureId, current);
                            throw;
                        }
                    }

                    // if current is 0, it means no upgrade/create method was found or succeeded
                    if (current == 0)
                    {
                        return;
                    }

                    dataMigrationRecord.Version = current;
                }
                catch (Exception ex)
                {
                    if (ex.IsFatal())
                    {
                        throw;
                    }
                    _logger.LogError(0, "Error while running migration version {0} for {1}.", current, featureId);
                    _session.Cancel();
                    throw new Exception(T["Error while running migration version {0} for {1}.", current, featureId], ex);
                }
                finally
                {
                    // Persist data migrations
                    _session.Save(_dataMigrationRecord);
                }
            }
        }
Esempio n. 2
0
        public async Task UpdateAsync(string featureId)
        {
            if (_processedFeatures.Contains(featureId))
            {
                return;
            }

            _processedFeatures.Add(featureId);

            if (_logger.IsEnabled(LogLevel.Information))
            {
                _logger.LogInformation("Updating feature '{FeatureName}'", featureId);
            }

            // proceed with dependent features first, whatever the module it's in
            var dependencies = _extensionManager
                               .GetFeatureDependencies(
                featureId)
                               .Where(x => x.Id != featureId)
                               .Select(x => x.Id);

            await UpdateAsync(dependencies);

            var migrations = GetDataMigrations(featureId);

            // apply update methods to each migration class for the module
            foreach (var migration in migrations)
            {
                var schemaBuilder = new SchemaBuilder(_store.Configuration, await _session.DemandAsync());
                migration.SchemaBuilder = schemaBuilder;

                // copy the object for the Linq query
                var tempMigration = migration;

                // get current version for this migration
                var dataMigrationRecord = await GetDataMigrationRecordAsync(tempMigration);

                var current = 0;
                if (dataMigrationRecord != null)
                {
                    // This can be null if a failed create migration has occured and the data migration record was saved.
                    current = dataMigrationRecord.Version.HasValue ? dataMigrationRecord.Version.Value : current;
                }
                else
                {
                    dataMigrationRecord = new Records.DataMigration {
                        DataMigrationClass = migration.GetType().FullName
                    };
                    _dataMigrationRecord.DataMigrations.Add(dataMigrationRecord);
                }

                try
                {
                    // do we need to call Create() ?
                    if (current == 0)
                    {
                        // try to resolve a Create method

                        var createMethod = GetCreateMethod(migration);
                        if (createMethod != null)
                        {
                            current = (int)createMethod.Invoke(migration, new object[0]);
                        }

                        // try to resolve a CreateAsync method

                        var createAsyncMethod = GetCreateAsyncMethod(migration);
                        if (createAsyncMethod != null)
                        {
                            current = await(Task <int>) createAsyncMethod.Invoke(migration, new object[0]);
                        }
                    }

                    var lookupTable = CreateUpgradeLookupTable(migration);

                    while (lookupTable.TryGetValue(current, out var methodInfo))
                    {
                        if (_logger.IsEnabled(LogLevel.Information))
                        {
                            _logger.LogInformation("Applying migration for '{FeatureName}' from version {Version}.", featureId, current);
                        }

                        var isAwaitable = methodInfo.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null;
                        if (isAwaitable)
                        {
                            current = await(Task <int>) methodInfo.Invoke(migration, new object[0]);
                        }
                        else
                        {
                            current = (int)methodInfo.Invoke(migration, new object[0]);
                        }
                    }

                    // if current is 0, it means no upgrade/create method was found or succeeded
                    if (current == 0)
                    {
                        return;
                    }

                    dataMigrationRecord.Version = current;
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error while running migration version {Version} for '{FeatureName}'.", current, featureId);

                    _session.Cancel();
                }
                finally
                {
                    // Persist data migrations
                    _session.Save(_dataMigrationRecord);
                }
            }
        }