Миграция данных в сервисную структуру Stateful Service - PullRequest
0 голосов
/ 21 мая 2018

У меня есть служба с отслеживанием состояния, которая хранит кучу данных о моих пользователях, которые хранятся в надежном словаре и, очевидно, также извлекает их оттуда.

Однако у меня также есть база данных SQL, которая использовал для хранения этой информации.При инициализации нового экземпляра службы с сохранением состояния мне нужно перенести эту информацию из базы данных SQL в новый механизм надежного хранения.С этого момента служба с сохранением состояния является источником правды.В идеале, я бы хотел отложить доступность моей службы с отслеживанием состояния до завершения процесса инициализации.

Есть ли какие-либо предложения относительно того, как это сделать?

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Я не уверен, правильно ли я вас понял.Но на основании вашего комментария я бы предложил следующее решение для возврата ответа «Не готов» во время миграции.

public interface IMigrationService
{
    bool IsDone();
}

public class MigrationService : IMigrationService
{
    private bool migrating = tu;

    public bool BeginMigration()
    {
        this.migrating = true;
    }
    public bool EndMigration()
    {
        this.migrating = false;
    }
    public bool IsDone()
    {
        return this.migrating;
    }
}

// WebHost startup class
public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // Register a middle-ware that would short circuit responses
        // while migration is in progress.
        app.Use(
            async (context, next) =>
            {
                var migrationService = 
                    context.RequestServices.GetService<IMigrationService>();
                if (!migrationService.IsDone())
                {
                    /* short circuit the response with approriate error message */
                }

                await next();
            });

        app.UseMvc();
    }
}

public class Stateful : StatefulService
{
    private readonly IMigrationService migrationService;

    public Stateful(StatefulServiceContext context)
      : base(context)
    { 
        this.migrationService = new MigrationService();
    }

    protected override IEnumerable<ServiceReplicaListener>
        CreateServiceReplicaListeners()
    {
        /* 
            Create a listener here with WebHostBuilder

            Use Startup class with the middle-ware defined and 
            add configure services -> .ConfigureServices() 
            with services.AddSingleton<IMigrationService>(this.migrationService)
        */
    }

    protected override async Task 
        RunAsync(CancellationToken cancellationToken)
    {
        this.migrationService.StartMigration();

        /* Migration code */

        this.migrationService.EndMigration();
    }
}

Это позволило бы вам развернуть новую версию службы, которая могла бы закорачиватьвсе запросы с соответствующим сообщением об ошибке во время миграции.

Надеюсь, это поможет.

0 голосов
/ 21 мая 2018

Нечто подобное сделает свое дело:

public interface IStateful1 : IService
{
    Task MyMethod();
}

internal sealed class Stateful1 : StatefulService, IStateful1
{
    private bool isReady = false; 

    public Stateful1(StatefulServiceContext context)
        : base(context)
    { }

    public Task MyMethod()
    {
        if(!isReady)
            throw new NotImplementedException(); // Probably throw or return something more meaningful :-) 

        return Task.CompletedTask; // Do your thing here
    }

    protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
    {
        return new ServiceReplicaListener[0];
    }

    protected override async Task RunAsync(CancellationToken cancellationToken)
    {
        await Task.Run(() => {
            // Simulation of some work
            Thread.Sleep((int)TimeSpan.FromMinutes(5).TotalMilliseconds);
        });

        isReady = true;
    }
}  

В этой настройке импорт из БД в надежную коллекцию выполняется методом RunAsync.

К сожалению, AFAIKнет способа подключить слушателей связи позже.Это упростило бы задачу.

Если бы CreateServiceReplicaListeners была бы асинхронной операцией, мы могли бы ожидать здесь задачу инициализации, но сейчас не можем.Использование .Wait() не сработает, так как сообщит, что запуск экземпляра занимает много времени, и пометит его как нездоровый.

Полный обзор жизненного цикла службы можно найти в Документы

...