示例#1
0
        public void RetryOnException_retries_the_given_number_of_times()
        {
            // arrange
            bool finished   = false;
            int  triesCount = 0;

            Action action =
                () =>
            {
                triesCount++;

                if (triesCount <= 3)
                {
                    throw new Exception();
                }
                else
                {
                    finished = true;
                }
            };

            // act
            RetryUtils.RetryOnException(
                new[] { typeof(Exception) },
                3,
                0,
                action);

            // assert
            Assert.AreEqual(4, triesCount);
            Assert.IsTrue(finished);
        }
示例#2
0
        public void RetryOnException_doesnt_retry_on_a_unexpected_exception()
        {
            // arrange
            int triesCount = 0;

            Action action =
                () =>
            {
                triesCount++;

                throw new ArgumentOutOfRangeException();
            };

            // act & assert
            Assert.Throws <ArgumentOutOfRangeException>(
                () =>
            {
                RetryUtils.RetryOnException(
                    new[] { typeof(InvalidOperationException) },
                    1,
                    0,
                    action);
            });

            Assert.AreEqual(1, triesCount);
        }
示例#3
0
        public void RetryOnException_retries_on_a_derived_exception()
        {
            // arrange
            bool finished   = false;
            int  triesCount = 0;

            Action action =
                () =>
            {
                triesCount++;

                if (triesCount == 1)
                {
                    throw new InvalidFilterCriteriaException();
                }
                else
                {
                    finished = true;
                }
            };

            // act
            RetryUtils.RetryOnException(
                new[] { typeof(ApplicationException) },
                1,
                0,
                action);

            // assert
            Assert.IsTrue(finished);
            Assert.AreEqual(2, triesCount);
        }
示例#4
0
        public async Task <bool> CheckAsync(bool testingEnvironment)
        {
            logger.LogInformation("Health checks starting.");
            try
            {
                logger.LogInformation($"API version: {Const.MERCHANT_API_VERSION}");
                logger.LogInformation($"Build version: {Const.MERCHANT_API_BUILD_VERSION}");

                RetryUtils.ExecAsync(() => TestDBConnection(), retry: 10, errorMessage: "Unable to open connection to database").Wait();
                ExecuteCreateDb();
                if (!testingEnvironment)
                {
                    await TestNodesConnectivityAndVersionAsync();
                    await CheckNodesZmqNotificationsAsync();
                    await TestMinerId();
                    await CheckBlocksAsync();
                    await MarkUncompleteNotificationsAsFailedAsync();
                }
                logger.LogInformation("Health checks completed successfully.");
            }
            catch (Exception ex)
            {
                logger.LogError("Health checks failed. {0}", ex.GetBaseException().ToString());
                // If exception was thrown then we stop the application. All methods in try section must pass without exception
                if (testingEnvironment)
                {
                    throw;
                }
                return(false);
            }

            return(true);
        }
示例#5
0
        public Task <ResultInfo> SendMessageAsync(CreateHelpRequest message, string appName = null)
        {
            return(RetryUtils.DoAsync(async() =>
            {
                var text = new StringBuilder();
                if (!string.IsNullOrEmpty(appName))
                {
                    text.AppendLine($"*AppName:* {appName}");
                }
                text.AppendLine($"*From:* {message.Email}");
                text.AppendLine($"*Subject:* {message.Subject}");
                text.AppendLine($"*Description:* {message.Description}");

                var slack = new SlackClient(_options.Url);
                var slackMessage = new SlackMessage()
                {
                    Channel = _options.Channel,
                    Text = text.ToString(),
                    Username = _options.Username,
                    IconEmoji = Emoji.Angel
                };
                return await slack.PostAsync(slackMessage) ? new ResultInfo(HttpStatusCode.OK) : new ResultInfo(HttpStatusCode.BadRequest, "Error in post message");
            },
                                      TimeSpan.FromMilliseconds(500),
                                      3,
                                      false,
                                      exception => { LoggerUtils.Log("SlackManager exception", exception, nameof(SlackManager)); }));
        }
示例#6
0
        /// <summary>
        /// Opens an excel file.
        /// </summary>
        /// <param name="path">File path.</param>
        public void OpenFile(string path)
        {
            WaitHelper.WaitFor(() => FileHelper.IsFileReady(path), 20);

            _workbook = RetryUtils.RetryIfThrown <COMException, Workbook>(() => _excelApp.Workbooks.Open(path),
                                                                          ConfigHelper.DefaultRetriesNumber, () => _workbook.Close());
        }
        public async Task <(decimal?, bool)> GetProductPrice(string shopID, string productID)
        {
            var productPriceQuery = @"
                query($shopId:Uuid!,$productType: String){shop(id: $shopId) {product(productType: $productType) { sellingPrice}}}";
            var queryVariables    = new
            {
                shopId      = shopID,
                productType = productID
            };

            try
            {
                var graphQLProductPriceData = await RetryUtils.RetryIfThrown <Exception, GraphQLResponse <GraphQLProductPriceData> >(async() =>
                                                                                                                                     await SendQueryAsync <GraphQLProductPriceData>(
                                                                                                                                         _clientUrl,
                                                                                                                                         productPriceQuery,
                                                                                                                                         queryVariables
                                                                                                                                         ), 10, 250, 1000);

                if (graphQLProductPriceData.Errors != null)
                {
                    _logger.LogWarning(ExceptionEvents.GenerateEventId(LoggerEventType.GraphQLClientQuery), $"Query error: {JsonConvert.SerializeObject(graphQLProductPriceData.Errors)}");
                    return(graphQLProductPriceData.Data?.Shop?.Product?.SellingPrice, false);
                }
                return(graphQLProductPriceData.Data?.Shop?.Product?.SellingPrice, true);
            }
            catch (Exception e)
            {
                var eventID = new EventId(0, $"Get Product Price: {shopID} , {productID}");
                _logger.LogError(eventID, e, "Error while getting product price");
                return(null, false);
            }
        }
示例#8
0
        private Node CreateNodeDb(Node node)
        {
            using var connection = new NpgsqlConnection(connectionString);
            RetryUtils.Exec(() => connection.Open());
            using var transaction = connection.BeginTransaction();

            string insertOrUpdate =
                "INSERT INTO Node " +
                "  (host, port, username, password, nodestatus, remarks) " +
                "  VALUES (@host, @port, @username, @password, @nodestatus, @remarks)" +
                "  ON CONFLICT (host, port) DO NOTHING " +
                "  RETURNING *"
            ;

            var now = clock.UtcNow();

            var insertedNode = connection.Query <Node>(insertOrUpdate,
                                                       new
            {
                host       = node.Host.ToLower(),
                port       = node.Port,
                username   = node.Username,
                password   = node.Password,
                nodestatus = node.Status,
                remarks    = node.Remarks
            },
                                                       transaction
                                                       ).SingleOrDefault();

            transaction.Commit();

            return(insertedNode);
        }
示例#9
0
        public void RetryOnException_throws_after_retries_count_is_exceeded()
        {
            // arrange
            int triesCount = 0;

            Action action =
                () =>
            {
                triesCount++;

                throw new ArgumentOutOfRangeException();
            };

            // act & assert
            Assert.Throws <ArgumentOutOfRangeException>(
                () =>
            {
                RetryUtils.RetryOnException(
                    new[] { typeof(ArgumentOutOfRangeException) },
                    1,
                    0,
                    action);
            });

            Assert.AreEqual(2, triesCount);
        }
示例#10
0
        private void ExecuteNonQuery(string command, string connectionString, object parameters = null)
        {
            using var connection = new NpgsqlConnection(connectionString);
            RetryUtils.Exec(() => connection.Open());

            connection.Execute(command, param: parameters);
        }
        protected override void DoExecute()
        {
            if (_directoryAdapter.Exists(_dstDirPath.Value))
            {
                RetryUtils.RetryOnException(
                    new[] { typeof(UnauthorizedAccessException) },
                    _DeleteDstDirRetriesCount,
                    _DeleteDstDirRetryDelay,
                    () =>
                {
                    _directoryAdapter.GetDirectories(_dstDirPath.Value)
                    .Where(x => !_excludedDirs.Any(s => x.EndsWith(s, StringComparison.CurrentCultureIgnoreCase)))
                    .ToList()
                    .ForEach(dirPath => _directoryAdapter.Delete(dirPath, true));

                    _directoryAdapter.GetFiles(_dstDirPath.Value)
                    .ToList()
                    .ForEach(_fileAdapter.Delete);
                });
            }
            else
            {
                _directoryAdapter.CreateDirectory(_dstDirPath.Value);
            }
        }
示例#12
0
        /// <exception cref="System.IO.IOException"/>
        private static ClientProtocol CreateNNProxyWithClientProtocol(IPEndPoint address,
                                                                      Configuration conf, UserGroupInformation ugi, bool withRetries, AtomicBoolean fallbackToSimpleAuth
                                                                      )
        {
            RPC.SetProtocolEngine(conf, typeof(ClientNamenodeProtocolPB), typeof(ProtobufRpcEngine
                                                                                 ));
            RetryPolicy defaultPolicy = RetryUtils.GetDefaultRetryPolicy(conf, DFSConfigKeys.
                                                                         DfsClientRetryPolicyEnabledKey, DFSConfigKeys.DfsClientRetryPolicyEnabledDefault
                                                                         , DFSConfigKeys.DfsClientRetryPolicySpecKey, DFSConfigKeys.DfsClientRetryPolicySpecDefault
                                                                         , typeof(SafeModeException));
            long version = RPC.GetProtocolVersion(typeof(ClientNamenodeProtocolPB));
            ClientNamenodeProtocolPB proxy = RPC.GetProtocolProxy <ClientNamenodeProtocolPB>(version
                                                                                             , address, ugi, conf, NetUtils.GetDefaultSocketFactory(conf), Client.GetTimeout(
                                                                                                 conf), defaultPolicy, fallbackToSimpleAuth).GetProxy();

            if (withRetries)
            {
                // create the proxy with retries
                IDictionary <string, RetryPolicy> methodNameToPolicyMap = new Dictionary <string, RetryPolicy
                                                                                          >();
                ClientProtocol translatorProxy = new ClientNamenodeProtocolTranslatorPB(proxy);
                return((ClientProtocol)RetryProxy.Create <ClientProtocol>(new DefaultFailoverProxyProvider
                                                                          <ClientProtocol>(typeof(ClientProtocol), translatorProxy), methodNameToPolicyMap
                                                                          , defaultPolicy));
            }
            else
            {
                return(new ClientNamenodeProtocolTranslatorPB(proxy));
            }
        }
示例#13
0
        /// <summary>
        /// Gets first worksheet.
        /// </summary>
        /// <returns>The worksheet.</returns>
        public Worksheet GetFirstWorksheet()
        {
            var worksheet = RetryUtils.RetryIfThrown <COMException, Worksheet>(() => (Worksheet)_workbook.Worksheets.Item[1],
                                                                               ConfigHelper.DefaultRetriesNumber, () => _workbook.Close());

            return(worksheet);
        }
        public async Task <ShopsData> GetShopsData()
        {
            var shopsDataQuery = @"{  shops { id }  productTypes { name }}";

            _logger.LogInformation("Fetching shops data...");

            try
            {
                var qraphQLShopsData = await RetryUtils.RetryIfThrown <Exception, GraphQLResponse <GraphQLShopsData> >(async() =>
                                                                                                                       await SendQueryAsync <GraphQLShopsData>(_clientUrl, shopsDataQuery), 10, 250, 1000);

                var shopsData = new ShopsData()
                {
                    ProductsIDs = qraphQLShopsData.Data.ProductTypes.Select(x => x.Name).ToList(),
                    ShopsIDs    = qraphQLShopsData.Data.Shops.Select(x => x.Id).ToList()
                };
                if (qraphQLShopsData.Errors != null)
                {
                    _logger.LogWarning($"Fetched shops data with warnings: {qraphQLShopsData.Errors}");

                    return(shopsData);
                }

                _logger.LogInformation("Fetched shops data successfully");
                return(shopsData);
            }
            catch (Exception e)
            {
                _logger.LogError(ExceptionEvents.GenerateEventId(LoggerEventType.GraphQLClient), e, "Error while getting shop data");
                return(null);
            }
        }
示例#15
0
 /// <summary>
 /// Sets a column values for selected rows.
 /// </summary>
 /// <param name="worksheet">The worksheet.</param>
 /// <param name="values">Key - number of row, value - value to set.</param>
 /// <param name="columnNumber">Number of column to set.</param>
 public void SetColumnValues(Worksheet worksheet, Dictionary <int, string> values, int columnNumber)
 {
     foreach (var value in values)
     {
         RetryUtils.RetryIfThrown <COMException, string>(() => worksheet.Cells[value.Key, columnNumber].Value = value.Value,
                                                         ConfigHelper.DefaultRetriesNumber, () => _workbook.Close());
     }
 }
        private NpgsqlConnection GetDbConnection()
        {
            var connection = new NpgsqlConnection(connectionString);

            RetryUtils.Exec(() => connection.Open());

            return(connection);
        }
        public static void EmptyRepository(string connectionString)
        {
            using var connection = new NpgsqlConnection(connectionString);
            RetryUtils.Exec(() => connection.Open());
            string cmdText =
                "TRUNCATE Tx, Block, TxMempoolDoubleSpendAttempt, TxBlockDoubleSpend, TxBlock, TxInput";

            connection.Execute(cmdText, null);
        }
示例#18
0
 private void DeleteTemporaryDirectoryIfNeeded()
 {
     if (!string.IsNullOrEmpty(_tempDirPath) && Directory.Exists(_tempDirPath))
     {
         RetryUtils.RetryOnException(
             new[] { typeof(IOException) },
             retriesCount: 4,
             retryDelay: 500,
             action: () => Directory.Delete(_tempDirPath, true));
     }
 }
示例#19
0
 public ForwarderMiddleware(RequestDelegate next, ILogger <ForwarderMiddleware> logger, IOptions <NodeConfig> config)
 {
     next_              = next ?? throw new ArgumentNullException(nameof(next));
     logger_            = logger;
     nodeConfig_        = config.Value;
     client.BaseAddress = new Uri(config.Value.ForwardUrl);
     client.Timeout     = TimeSpan.FromSeconds(nodeConfig_.HttpClientTimeoutInSeconds);
     retryPolicy_       = Policy
                          .Handle <Exception>()
                          .WaitAndRetryAsync(RetryUtils.DecorrelatedJitter
                                             (
                                                 nodeConfig_.ForwarderMaxRetries,
                                                 TimeSpan.FromMilliseconds(nodeConfig_.ForwarderFirstRetryDelayInMillis),
                                                 TimeSpan.FromSeconds(nodeConfig_.ForwarderMaxRetryDelayInSeconds)
                                             ));
 }
示例#20
0
        public void DeleteFile(string fileId)
        {
            void deleteFile()
            {
                RetryUtils.Do(() => FileUtils.DeleteDirectory(_getDirectoryPath(fileId)), TimeSpan.FromSeconds(1));
            }

            if (_fileManagerOptions.Impersonation.IsImpersonationEnabled)
            {
                Impersonation.RunAsUser(_userCredentialsImpersonation, deleteFile);
            }
            else
            {
                deleteFile();
            }
        }
示例#21
0
        public void PerformAs(User user)
        {
            Element.WithId(id).CanBeFoundOnThePageBy(user);
            try
            {
                Log.Action($"clicking the element with id {this.id}");

                RetryUtils.RetryIfThrown <Exception, Boolean>(() =>
                {
                    return(ClickElement(user, id));
                }, 10, 250);
            }
            catch (Exception)
            {
                throw Log.Exception($"Unable to click on the element with id:  {this.id}");
            }
        }
        public bool ShouldRetry(Exception exception, int attempt, out TimeSpan delay)
        {
            //Ask the underlying retry policy for the retry parameters.
            var retryParameters = this.retryPolicy.GetRetryParameters(attempt, exception);

            delay = retryParameters.WaitTime;

            //The underlying retry policy does not know about InvalidExpectedStatusCodeException
            //so we handle that here. For everything else we defer back to the underlying retry policy
            var invalidStatusCodeException = exception as InvalidExpectedStatusCodeException;

            if (invalidStatusCodeException != null)
            {
                return(RetryUtils.IsTransientHttpStatusCode(invalidStatusCodeException.ReceivedStatusCode));
            }
            return(retryParameters.ShouldRetry);
        }
示例#23
0
        public void CreateVersionTable(string connectionString)
        {
            using var connection = new NpgsqlConnection(connectionString);
            RetryUtils.Exec(() => connection.Open());

            string createVersionTable = @"
      CREATE TABLE Version (
		      versionId		SERIAL		NOT NULL,
		      projectName		VARCHAR(256) NOT NULL,
		      updating			INTEGER			NOT NULL,
	       creationDate			TIMESTAMP NOT NULL,
	
		      PRIMARY KEY (versionid)
      );
      ALTER TABLE Version ADD CONSTRAINT version_versionIdAndProjectName UNIQUE (versionId,projectName);";

            connection.Execute(createVersionTable, null);
        }
示例#24
0
        public void ExecuteFileScript(string connectionString, string filepath, System.Text.Encoding encoding, int commandTimeout, bool createDB = false)
        {
            using var connection = new NpgsqlConnection(connectionString);
            string command = File.ReadAllText(filepath, encoding);

            RetryUtils.Exec(() => connection.Open());

            if (createDB) // create database cannot run inside a transaction block
            {
                connection.Execute(command, commandTimeout: commandTimeout);
            }
            else
            {
                using var transaction = connection.BeginTransaction();
                connection.Execute(command, transaction: transaction, commandTimeout: commandTimeout);
                transaction.Commit();
            }
        }
示例#25
0
        public Task <ResultInfo> AddRequestAsync(CreateHelpRequest model)
        {
            return(RetryUtils.DoAsync(async() =>
            {
                var baseUrl = new Uri(new Uri(_options.Url), _addRequestApiMethod);
                var client = new RestClient(baseUrl);

                var request = new RestRequest(Method.POST);
                var outgoingQueryString = HttpUtility.ParseQueryString(string.Empty);
                outgoingQueryString.Add("apikey", _options.ApiKey);
                outgoingQueryString.Add("group", _options.Group);
                outgoingQueryString.Add("businessUnit", _options.BusinessUnit);
                outgoingQueryString.Add("email", model.Email);
                outgoingQueryString.Add("subject", model.Subject);
                outgoingQueryString.Add("description", model.Description);
                var postdata = outgoingQueryString.ToString();

                request.AddParameter("application/x-www-form-urlencoded", postdata, ParameterType.RequestBody);

                var response = await client.ExecuteTaskAsync(request);

                if (!response.IsSuccessful)
                {
                    LoggerUtils.Log($"HelpDesk API request was failed with code: {response.StatusCode}" + Environment.NewLine
                                    + $"Response: {response.Content}",
                                    _logFileName);
                    return new ResultInfo(response.StatusCode, _invalidRequestMessage);
                }

                var responseModel = JsonConvert.DeserializeObject <CreateHelpDeskRequestResponse>(response.Content);

                if (responseModel.Response.Result.Status == CreateHelpDeskRequestResponse.Status.Failure)
                {
                    LoggerUtils.Log($"HelpDesk API AddRequest was failed with message: {responseModel.Response.Result.Message}", _logFileName);
                    return new ResultInfo(HttpStatusCode.BadRequest, _invalidRequestMessage);
                }

                return new ResultInfo(HttpStatusCode.OK);
            },
                                      TimeSpan.FromMilliseconds(500),
                                      3,
                                      false,
                                      exception => { LoggerUtils.Log("HelpDeskManager exception", exception, _logFileName); }));
        }
示例#26
0
        public void EvaluateResponse(HttpResponseMessage response)
        {
            if (response == null)
            {
                return;
            }

            HttpStatusCode httpStatusCode = response.StatusCode;

            if (httpStatusCode == HttpStatusCode.OK)
            {
                return;
            }

            String reasonPhrase = response.ReasonPhrase;

            if (httpStatusCode == HttpStatusCode.BadRequest)
            {
                throw new FcmBadRequestException(reasonPhrase);
            }

            if (httpStatusCode == HttpStatusCode.Unauthorized)
            {
                throw new FcmAuthenticationException(reasonPhrase);
            }

            int httpStatusCodeIntegerValue = Convert.ToInt32(httpStatusCode);

            if (httpStatusCodeIntegerValue >= 500 && httpStatusCodeIntegerValue < 600)
            {
                RetryConditionValue retryConditionValue;

                if (RetryUtils.TryDetermineRetryDelay(response, out retryConditionValue))
                {
                    throw new FcmRetryAfterException(reasonPhrase, retryConditionValue);
                }
            }

            throw new FcmGeneralException(reasonPhrase);
        }
示例#27
0
        public void GetCurrentVersion(string projectName, string connectionString, out int currentVersion, out bool updating)
        {
            using var connection = new NpgsqlConnection(connectionString);

            try
            {
                // check if Version table exists (it is possible, that user doesn't have rights to access user_tables
                if (ExistsVersionTable(connectionString))
                {
                    RetryUtils.Exec(() => connection.Open());
                    string selectCommand = $"SELECT max(versionid) versionid, max(updating) updating FROM Version WHERE upper(projectname) = upper('{ projectName }') group by versionid having max(versionid) = (select max(versionid) from Version WHERE upper(projectname) = upper('{ projectName }'))";
                    var    version       = connection.QueryFirstOrDefault <Version>(selectCommand);

                    if (version == null)
                    {
                        // Version table has no rows
                        currentVersion = -1;
                        updating       = false;
                    }
                    else
                    {
                        currentVersion = version.VersionId;
                        updating       = version.Updating == 1;
                    }
                }
                else
                {
                    // Version table does not exist
                    currentVersion = -1;
                    updating       = false;
                }
            }
            catch (Exception e)
            {
                currentVersion = -1;
                updating       = false;
                throw e;
            }
        }
示例#28
0
 /// <summary>
 /// Saves a workbook and close it.
 /// </summary>
 public void SaveWorkbookAndClose()
 {
     RetryUtils.RetryIfThrown <COMException>(() => _workbook.Save(), ConfigHelper.DefaultRetriesNumber);
     RetryUtils.RetryIfThrown <COMException>(() => _workbook.Close(), ConfigHelper.DefaultRetriesNumber);
 }
        /// <summary>
        /// Deletes node data directory (if exists) and start new instance of bitcoind
        /// </summary>
        public BitcoindProcess(string hostIp, string bitcoindFullPath, string dataDir, int p2pPort, int rpcPort, string zmqIp, int zmqPort, ILoggerFactory loggerFactory, bool emptyDataDir = true)
        {
            this.Host        = hostIp;
            this.P2Port      = p2pPort;
            this.RpcPort     = rpcPort;
            this.RpcUser     = "******";
            this.RpcPassword = "******";
            this.ZmqIp       = zmqIp;
            this.ZmqPort     = zmqPort;
            this.logger      = loggerFactory.CreateLogger <BitcoindProcess>();


            if (!ArePortsAvailable(p2pPort, rpcPort))
            {
                throw new Exception(
                          "Can not start a new instance of bitcoind. Specified ports are already in use. There might be an old version of bitcoind still running. Terminate it manually and try again-");
            }

            if (emptyDataDir)
            {
                if (Directory.Exists(dataDir))
                {
                    var regtest = Path.Combine(dataDir, "regtest");
                    if (Directory.Exists(regtest))
                    {
                        logger.LogInformation($"Old regtest directory exists. Removing it: {regtest}");
                        Directory.Delete(regtest, true);
                    }
                }
                else
                {
                    Directory.CreateDirectory(dataDir);
                }
            }
            else
            {
                if (!Directory.Exists(dataDir))
                {
                    throw new Exception("Data directory does not exists. Can not start new instance of bitcoind");
                }
            }


            // use StartupInfo.ArgumentList instead of StartupInfo.Arguments to avoid problems with spaces in data dir
            var argumentList = new List <string>(defaultParams.Split(" ").ToList());

            argumentList.Add($"-port={p2pPort}");
            argumentList.Add($"-rpcport={rpcPort}");
            argumentList.Add($"-datadir={dataDir}");
            argumentList.Add($"-rpcuser={RpcUser}");
            argumentList.Add($"-rpcpassword={RpcPassword}");
            argumentList.Add($"-zmqpubhashblock=tcp://{ZmqIp}:{zmqPort}");
            argumentList.Add($"-zmqpubinvalidtx=tcp://{ZmqIp}:{zmqPort}");
            argumentList.Add($"-zmqpubdiscardedfrommempool=tcp://{ZmqIp}:{zmqPort}");
            argumentList.Add($"-invalidtxsink=ZMQ");

            logger.LogInformation($"Starting {bitcoindFullPath} {string.Join(" ",argumentList.ToArray())}");

            var localProcess = new Process();
            var startInfo    = new ProcessStartInfo(bitcoindFullPath);

            foreach (var arg in argumentList)
            {
                startInfo.ArgumentList.Add(arg);
            }

            localProcess.StartInfo = startInfo;
            try
            {
                if (!localProcess.Start())
                {
                    throw new Exception($"Can not invoke {bitcoindFullPath}");
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"Can not invoke {bitcoindFullPath}. {ex.Message}", ex);
            }

            this.process = localProcess;
            string bestBlockhash = null;


            var rpcClient = new RpcClient(RpcClientFactory.CreateAddress(Host, rpcPort),
                                          new System.Net.NetworkCredential(RpcUser, RpcPassword), loggerFactory.CreateLogger <RpcClient>());

            try
            {
                RetryUtils.Exec(() => { bestBlockhash = rpcClient.GetBestBlockHashAsync().Result; }, 10, 100);
            }
            catch (Exception e)
            {
                logger.LogError($"Can not connect to test node {e.Message}");
                throw new Exception($"Can not connect to test node", e);
            }

            this.RpcClient = rpcClient;
            if (emptyDataDir)
            {
                var height = rpcClient.GetBlockHeaderAsync(bestBlockhash).Result.Height;
                if (height != 0)
                {
                    throw new Exception(
                              "The node that was just started does not have an empty chain. Can not proceed. Terminate the instance manually. ");
                }
            }

            logger.LogInformation($"Started bitcoind process pid={localProcess.Id } rpcPort={rpcPort}, p2pPort={P2Port}, dataDir={dataDir}");
        }