Ejemplo n.º 1
0
        public WriteCache(IOperationCacheRepository transactionCacheRepository, ILogger <WriteCache> logger, bool persistToDisk = true)
        {
            _operationCacheRepository = transactionCacheRepository;
            _logger        = logger;
            _persistToDisk = persistToDisk;

            //Load persistent queue into memory
            if (_persistToDisk)
            {
                _logger.LogDebug("Loading transactions to queue...");
                OperationQueue = _operationCacheRepository.GetOperationQueueAsync().GetAwaiter().GetResult().ToList();
                TransitQueue   = _operationCacheRepository.GetTransitQueueAsync().GetAwaiter().GetResult().ToList().ToDictionary(swo => swo.Id, swo => swo);
            }
            else
            {
                _logger.LogWarning("Queue has been set to transient mode. Queue data will not be persisted to disk");
            }
        }
Ejemplo n.º 2
0
        public DataService(
            ILoggerFactory loggerFactory,
            IShardRepository shardRepository,
            IDataRouter dataRouter,
            IStateMachine <State> stateMachine,
            NodeStateService nodeStateService,
            ClusterClient clusterClient,
            IOptions <ClusterOptions> clusterOptions,
            IOperationCacheRepository transactionCacheRepository,
            IOptions <NodeOptions> nodeOptions)
        {
            _nodeStateService = nodeStateService;
            _nodeOptions      = nodeOptions.Value;
            _clusterOptions   = clusterOptions.Value;
            _stateMachine     = stateMachine;
            _writeCache       = new WriteCache(transactionCacheRepository, loggerFactory.CreateLogger <WriteCache>(), _nodeOptions.PersistWriteQueue);
            _logger           = loggerFactory.CreateLogger <DataService <State> >();
            _shardRepository  = shardRepository;
            _clusterClient    = clusterClient;
            Reader            = new Reader <State>(
                loggerFactory.CreateLogger <Reader <State> >(),
                shardRepository,
                dataRouter,
                stateMachine,
                nodeStateService,
                clusterClient);;
            Allocator = new Allocator <State>(
                loggerFactory.CreateLogger <Allocator <State> >(),
                shardRepository,
                dataRouter,
                stateMachine,
                nodeStateService,
                clusterClient);
            Writer = new Writer <State>(loggerFactory.CreateLogger <Writer <State> >(),
                                        shardRepository,
                                        dataRouter,
                                        stateMachine,
                                        nodeStateService,
                                        clusterClient
                                        );
            Syncer = new Syncer <State>(shardRepository, loggerFactory.CreateLogger <Syncer <State> >(), stateMachine, clusterClient, nodeStateService, Writer);



            _writeTask = new Task(async() =>
            {
                //Before you write you should first dequeue all transactions
                if (_writeCache.TransitQueue.Count() > 0)
                {
                    _logger.LogInformation("Found transactions in transit, attempting to reapply them...");
                    foreach (var operationKV in _writeCache.TransitQueue.ToDictionary(entry => entry.Key, entry => entry.Value))
                    {
                        var operation = operationKV.Value;
                        try
                        {
                            var result = await Writer.WriteShardData(operation.Data, operation.Operation, operation.Id, operation.TransactionDate);
                        }
                        catch (Exception e)
                        {
                            _logger.LogError("Failed to apply operation " + operation.Id + " with exception " + e.Message + Environment.NewLine + e.StackTrace);
                            try
                            {
                                await _writeCache.CompleteOperation(operation.Id);
                            }
                            catch (Exception completionError)
                            {
                                _logger.LogError("Error removing operation from transit queue with error " + completionError.Message + Environment.NewLine
                                                 + completionError.StackTrace + Environment.NewLine + JsonConvert.SerializeObject(operation, Formatting.Indented));
                            }
                        }
                    }
                }

                while (true)
                {
                    try
                    {
                        var operation = await _writeCache.DequeueOperation();
                        if (operation != null)
                        {
                            try
                            {
                                var result = await Writer.WriteShardData(operation.Data, operation.Operation, operation.Id, operation.TransactionDate);
                            }
                            catch (Exception e)
                            {
                                _logger.LogError("Failed to write operation with exception " + e.Message + Environment.NewLine + JsonConvert.SerializeObject(operation, Formatting.Indented));
                            }
                            await _writeCache.CompleteOperation(operation.Id);
                        }
                        else
                        {
                            //Release write thread for a small amount of time
                            await Task.Delay(100);
                        }
                    }
                    catch (Exception e)
                    {
                        _logger.LogError("Encountered critical write error " + e.Message + Environment.NewLine + e.StackTrace);
                    }
                }
            });
            _writeTask.Start();
            TaskUtility.RestartTask(ref _indexCreationTask, async() => await CreateIndexLoop());

            _allocationTask = new Task(async() => await AllocateShards());
            _allocationTask.Start();
            _replicaValidationChecksTask = Task.Run(async() => await CheckAllReplicas());

            _objectLockWatcher = new Task(async() => await CheckLocks());
            _objectLockWatcher.Start();


            if (_nodeOptions.EnablePerformanceLogging)
            {
                var performancePrinting = new Task(() =>
                {
                    while (true)
                    {
                        Console.Clear();
                        Console.WriteLine("Performance Report...");
                        foreach (var value in totals)
                        {
                            Console.WriteLine(value.Key + ":" + (value.Value / totalRequests));
                        }
                        Console.WriteLine("Queue:" + _writeCache.OperationsInQueue);
                        Task.Delay(1000);
                    }
                });
                performancePrinting.Start();
            }
        }