Skip to content

Instantly share code, notes, and snippets.

@bvasilenko
Created November 18, 2017 20:20
Show Gist options
  • Save bvasilenko/b5d26da9e894878390aa055875f6e9bd to your computer and use it in GitHub Desktop.
Save bvasilenko/b5d26da9e894878390aa055875f6e9bd to your computer and use it in GitHub Desktop.
namespace Sync.Task.Mirror
{
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Practices.Unity;
using Sync.Entities;
using Sync.Identity.Data.DataContexts;
using Sync.Infrastructure;
using Sync.Infrastructure.Enumerable;
using Sync.Infrastructure.Exceptions;
using Sync.Infrastructure.Unity;
using Sync.Provisioning;
using Sync.Provisioning.Entities;
using Sync.Task.Mirror.Processors;
class Program
{
private const int DatabasesPerSession = 100;
private readonly AccountDataContext accountDataContext;
private readonly IEnsureReplicatonProcessor ensureReplicatonProcessor;
private readonly ICancelReplicationProcessor cancelReplicationProcessor;
private readonly IPutSecurityProcessor putSecurityProcessor;
private readonly IConfiguration configuration;
private readonly ILogger logger;
private readonly ISyncProvisioningService provisioningService;
static void Main(string[] arguments)
{
try
{
Singleton<UnityContainer>.Instance
.RunConfigurator<MirrorUnityConfigurator>()
.Resolve<Program>()
.Run(arguments.Contains("/cancel"))
.Wait();
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
public Program(
AccountDataContext accountDataContext,
IEnsureReplicatonProcessor ensureReplicatonProcessor,
ICancelReplicationProcessor cancelReplicationProcessor,
IPutSecurityProcessor putSecurityProcessor,
IConfiguration configuration,
ILogger logger,
ISyncProvisioningService provisioningService)
{
this.accountDataContext = accountDataContext;
this.ensureReplicatonProcessor = ensureReplicatonProcessor;
this.cancelReplicationProcessor = cancelReplicationProcessor;
this.putSecurityProcessor = putSecurityProcessor;
this.configuration = configuration;
this.logger = logger;
this.provisioningService = provisioningService;
}
private async Task Run(bool cancel)
{
try
{
var source = await this.GetSyncServer(this.configuration.SourceServer);
var target = await this.GetSyncServer(this.configuration.TargetServer);
var server = new Server(source.Url);
var authData = new AuthData(source.ServiceUser, source.ServiceSecret);
var databases = await this.provisioningService.GetDatabases(server, authData);
var tasks = await this.provisioningService.GetReplicationTasks(server, authData);
Parallel.ForEach(databases.Slice(DatabasesPerSession),
sliceOfDatabases =>
this.ProcessDatabases(source, target, sliceOfDatabases, tasks, cancel)
.Wait());
}
catch (Exception exception)
{
this.logger.LogError(exception,
string.Format("{0}.Unhandled.{1}", this.GetType().Namespace, exception.GetType().FullName));
throw;
}
}
private async Task ProcessDatabases(SyncServer source, SyncServer target, IEnumerable<string> databases, IDictionary<string, IEnumerable<ReplicationTask>> existingTasks, bool cancel)
{
var server = new Server(source.Url);
var authData = new AuthData(source.ServiceUser, source.ServiceSecret);
var session = await this.provisioningService.StartSession(server, authData);
foreach (var database in
databases.Where(database => !this.configuration.ExcludeDatabases.Contains(database)))
{
var context = new DatabaseContext(server, session, database, target, existingTasks);
if (cancel)
{
await this.cancelReplicationProcessor.Run(context);
}
else
{
await this.ensureReplicatonProcessor.Run(context);
await this.putSecurityProcessor.Run(context);
}
}
}
private async Task<SyncServer> GetSyncServer(string serverName)
{
try
{
return await this.accountDataContext.SyncServers.FirstAsync(syncServer => syncServer.Name == serverName);
}
catch (Exception exception)
{
throw new SyncException(string.Format("Unable to find server '{0}'", serverName), exception);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment