#include "multithread_client.h"

namespace NSaas {
    namespace {
        THolder<IThreadPool> CreateQueue(size_t threadsCount, size_t queueSizeLimit, bool blocking = true, const TString& name = {}) {
            THolder<IThreadPool> queue;
            if (threadsCount > 1) {
                queue.Reset(new TThreadPool(TThreadPool::TParams().SetBlocking(blocking).SetCatching(true).SetThreadName(name)));
            }
            else {
                queue.Reset(new TFakeThreadPool());
            }
            queue->Start(threadsCount, queueSizeLimit);
            return queue;
        }
    }

    TMultithreadIndexer::TMultithreadIndexer(const TMultithreadIndexerOption& options)
        : Options(options)
        , Client(Options.Host, Options.Port, "/service/" + Options.IndexKey)
        , Sloth(TDuration::Zero(), Options.MinSleepDuration, Options.MaxSleepDuration)
    {
        Y_ASSERT(!options.IndexKey.empty());
        Y_ASSERT(!options.Host.empty());
        Queue = CreateQueue(Options.Threads, Options.QueueSize, Options.Blocking, "MultiThrIndexer");
    }

    void TMultithreadIndexer::IndexDocument(TAtomicSharedPtr<TAction> action, TResultCallback resultCb) {
        Y_VERIFY(Queue);
        Queue->SafeAddFunc([this, action, resultCb]() {
            NSaas::TSendResult result;
            for (ui32 i = 0; i < 1 + Options.ReindexAttemptions; ++i) { // one initial attempt + number of retries
                Sloth.Sleep();
                result = Client.Send(*action, Options.RtyIndexAdapter, Options.SendParams);
                if (result.GetCode() == TSendResult::srOK) {
                    Sloth.DecDuration();
                    break;
                }
                Sloth.IncDuration();
            }

            if (result.GetCode() != TSendResult::srOK) {
                resultCb(result, *action);
            }
        });
    }

}
