private async Task <PrepareResult> SendRequestToOneNode(IInternalSession session, IEnumerator <Host> queryPlan, InternalPrepareRequest request)
        {
            var triedHosts = new Dictionary <IPEndPoint, Exception>();

            while (true)
            {
                // It may throw a NoHostAvailableException which we should yield to the caller
                var hostConnectionTuple = await GetNextConnection(session, queryPlan, triedHosts).ConfigureAwait(false);

                var connection = hostConnectionTuple.Item2;
                var host       = hostConnectionTuple.Item1;
                try
                {
                    var result = await connection.Send(request).ConfigureAwait(false);

                    return(new PrepareResult
                    {
                        PreparedStatement = await GetPreparedStatement(result, request, request.Keyspace ?? connection.Keyspace, session.Cluster).ConfigureAwait(false),
                        TriedHosts = triedHosts,
                        HostAddress = host.Address
                    });
                }
                catch (Exception ex) when(PrepareHandler.CanBeRetried(ex))
                {
                    triedHosts[host.Address] = ex;
                }
            }
        }
        /// <summary>
        /// Executes the prepare request on the first host selected by the load balancing policy.
        /// When <see cref="QueryOptions.IsPrepareOnAllHosts"/> is enabled, it prepares on the rest of the hosts in
        /// parallel.
        /// </summary>
        internal static async Task <PreparedStatement> Prepare(IInternalSession session, Serializer serializer,
                                                               PrepareRequest request)
        {
            var cluster = session.InternalCluster;
            var lbp     = cluster.Configuration.Policies.LoadBalancingPolicy;
            var handler = new PrepareHandler(serializer, lbp.NewQueryPlan(session.Keyspace, null).GetEnumerator());
            var ps      = await handler.Prepare(request, session, null).ConfigureAwait(false);

            var psAdded = cluster.PreparedQueries.GetOrAdd(ps.Id, ps);

            if (ps != psAdded)
            {
                Logger.Warning("Re-preparing already prepared query is generally an anti-pattern and will likely " +
                               "affect performance. Consider preparing the statement only once. Query='{0}'", ps.Cql);
                ps = psAdded;
            }
            var prepareOnAllHosts = cluster.Configuration.QueryOptions.IsPrepareOnAllHosts();

            if (!prepareOnAllHosts)
            {
                return(ps);
            }
            await handler.PrepareOnTheRestOfTheNodes(request, session).ConfigureAwait(false);

            return(ps);
        }