ExecutorService timeout bez przerywania wątku

ExecutorService timeout bez przerywania wątku
MA
  • Rejestracja:ponad 3 lata
  • Ostatnio:2 miesiące
  • Postów:30
0

Hej,
musze procesować jedną operację asynchronicznie.
Chciałem zastosować ExecutorService + Future.
Challenge jest taki, że jeśli procesowanie będzie trwało ponad 60 sekund to:

  1. mam zwrócić warning do klienta
  2. mam NIE przerywać procesowania.

Ze względu na AD2 wydaje mi się, że Future.get(timeout) odpada bo to przerwie procesowanie.

Pomysły?

pedegie
  • Rejestracja:około 11 lat
  • Ostatnio:ponad rok
  • Postów:204
0

Nie przerwie procesowania, możesz spokojnie podpiąć .orTimeout() i w whenComplete / completeOnTimeout (w zależności jak to chcesz zwracać, są też inne operatory) wtedy sprawdzić czy error == TimeoutException i zwrócić co tam trzeba.

Future.get() odpada, bo nie będzie asynchronicznie :)

EDIT: to jeszcze też zależy z jaką wersją Javy pracujesz, jak masz Future'a i Executora to conajmniej 1.5 jest na pewno, jeśli < 8 to nie masz CompletableFuture'a a jeśli < 9 to nie masz fajnych operatorów - będziesz musiał zakodzić trochę wiecej sam, jak >=9 to masz w zasadzie cały arsenał concurrency dostępny, więc najlepiej zacząć od: CompletableFuture.supplyAsync(() -> job(), executor)

edytowany 6x, ostatnio: pedegie
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 21 godzin
  • Postów:1875
1

Hmm może chodziło o to, ze po 60 sekundach ma polecieć timeout na requescie HTTP. No bo co ma się dziać z requestem podczas procesowania joba?

Możesz zdelegowac obsługę joba do osobnej puli wątków jak chciałeś, a wątek serwera zawiesić na CountDownLatch z timeoutem 60 sekund (job jak się skończy podnosi latcha). Tylko to jest o tyle dziwne, że jak trzeba będzie obsłużyć wiele takich zadań, to zablokuje Ci serwer - wszystkie wątki będą wisieć :)

Powinieneś od razu zwrócić do klienta HTTP 202 i dać mu jakiś endpoint do obserwowania statusu zadania. Czyli pierwotny problem jest źle zdefiniowany - tak się nie robi rzeczy.


”Engineering is easy. People are hard.” Bill Coughran
edytowany 6x, ostatnio: Charles_Ray
MA
  • Rejestracja:ponad 3 lata
  • Ostatnio:2 miesiące
  • Postów:30
0

Właśnie to nie ma być HTTP timeout bo my otrzymujemy request i musimy wiedzieć, że sami zrobiliśmy timeout.

Ogólnie aby to uszczegółowić.

  1. Wpada request
  2. Zaczynamy procesować asynchronicznie
  3. Jeśli procesowanie trwa więcej niż 60 sec to zwracamy warning - tutaj chodzi o to, aby klient wiedzial, że przyjeliśmy request do procesowania a nie zwykly http timeout
  4. Jeśli procesowanie zakończyło się wcześniej niz 60 sec to zwracamy jakieś tam rezultaty procesowania które wynikają z tego procesowania asynchronicznego.
edytowany 1x, ostatnio: mariankon
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 21 godzin
  • Postów:1875
1

Czyli chcecie odpowiadać w 60 sekund? Przecież to się wszystko zwiesi ;) no ale dobra - rozwiązanie z latchem powinno być ok, możecie sobie TimeoutException obsłużyć w taki sposób, że zwrocicie 2xx z messagem, że przekroczono 60 sekund. Czyli musisz zawiesić wątek serwera obsługujący request HTTP. Ważne żeby sam request nie stimeoutował się wcześniej.

Można by tez coś kombinować z RxJavą - zrobić 2 observable i poczekać, który szybciej się skończy. Tak byłoby mniej kodu i bardziej deklaratywnie. Minusem jest RxJava :)


”Engineering is easy. People are hard.” Bill Coughran
edytowany 1x, ostatnio: Charles_Ray
W0
  • Rejestracja:ponad 12 lat
  • Ostatnio:14 minut
  • Postów:3588
0

Jeśli nie zależy ci na wielkiej dokładności to można ogarnąć przez promise'y, z jakiegoś niezrozumiałego dla mnie powodu nazwane w Javie CompletableFuture:

Kopiuj
    /**
     * Will print "DONE" only 
     */
    private static void test2() throws ExecutionException, InterruptedException {
        var main = Executors.newSingleThreadExecutor();
        var notifier = Executors.newSingleThreadExecutor();

        CompletableFuture<String> myLongTask = CompletableFuture.supplyAsync(() -> myLongTask(3), main);
        CompletableFuture<Void> notifyTask = CompletableFuture.runAsync(() -> notifyCustomer(5), notifier);

        myLongTask.whenComplete((l, r) -> notifyTask.cancel(true));

        System.out.println(myLongTask.get());
        main.shutdownNow();
        notifier.shutdownNow();
    }

    /**
     * Will print "LONG_TIME" and "DONE"
     */
    private static void test1() throws ExecutionException, InterruptedException {
        var main = Executors.newSingleThreadExecutor();
        var notifier = Executors.newSingleThreadExecutor();

        CompletableFuture<String> myLongTask = CompletableFuture.supplyAsync(() -> myLongTask(10), main);
        CompletableFuture<Void> notifyTask = CompletableFuture.runAsync(() -> notifyCustomer(5), notifier);

        myLongTask.whenComplete((l, r) -> notifyTask.cancel(true));

        System.out.println(myLongTask.get());
        main.shutdownNow();
        notifier.shutdownNow();
    }

    private static Void notifyCustomer(int timeSeconds) {
        try {
            Thread.sleep(timeSeconds*1000);
            System.out.println("LONG_TIME");
        } catch (InterruptedException e) {
            // do nothing
        }

        return null;
    }

    private static String myLongTask(int timeSeconds) {
        try {
            Thread.sleep(timeSeconds*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return "DONE";
    }
pedegie
  • Rejestracja:około 11 lat
  • Ostatnio:ponad rok
  • Postów:204
3
Kopiuj
public class Test
{
    private static final ScheduledExecutorService timeouter = Executors.newSingleThreadScheduledExecutor();
    private static final ExecutorService executor = Executors.newSingleThreadExecutor();

    public static void main(String[] args)
    {
        CompletableFuture<String> cf = CompletableFuture.supplyAsync(Test::someJob, executor)
                .applyToEither(timeoutAfter(2, TimeUnit.SECONDS), response -> response)
                .exceptionally(throwable -> "WARNING");

        String result = cf.join();
        System.out.println(result);

    }

    private static String someJob()
    {
        LockSupport.parkNanos((long) 5e9);
        System.out.println("PROCESSED");
        return "RESPONSE";
    }


    private static <T> CompletableFuture<T> timeoutAfter(long timeout, TimeUnit unit) {
        CompletableFuture<T> result = new CompletableFuture<T>();
        timeouter.schedule(() -> result.completeExceptionally(new TimeoutException()), timeout, unit);
        return result;
    }
}

Coś takiego na kolanie na szybko jak java 8

EDIT: tylko tak jak @Charles_Ray wspomniał, jakby założyć mocno pesymistyczny scenariusz, w którym ten job sie nie wyrabia (a warto taki założyć) to tam wszystko siądzie, szczególnie że jest 1 wątek procesujący

edytowany 1x, ostatnio: pedegie
Zobacz pozostały 1 komentarz
pedegie
w RxJavie ladniej by wygladalo ^^
pedegie
hmm w tym moim rozwiązaniu trochę oszukujemy z emitowaniem elementu, wydaje mi się że powinien być jakis operator bardziej pasujący do problemu autora - w reactor.io jest (np timeoutMillis()), nie wiem jak w rx
Charles_Ray
Tak, ale w jakiś sposób musisz „zjoinować” strumień „z timeoutem” (który kończy się za 60s) ze strumieniem obsługującym joba (przy okazji schedulujesz go na osobnej puli) - czekasz na pierwszy z nich. Dzięki temu całkowity czas czekania to 60s. Tak to rozumiem ;)
MA
  • Rejestracja:ponad 3 lata
  • Ostatnio:2 miesiące
  • Postów:30
0

Dzięki Panowie,
samo przyjmowanie requestów jest ogarnięte na kilkunastu wątkach także nie będzie problemu z tym, że coś siądzie przez to, że czekamy max 60sek.
Dzięki jeszcze raz

Charles_Ray
Sprawdziłbym to :) powiedzmy ze masz na serwerze pule 100 wątków, spróbuj odpalić curlem 101 requestow :)
MA
  • Rejestracja:ponad 3 lata
  • Ostatnio:2 miesiące
  • Postów:30
0

@pedegie: Tylko zastanawiam się nad jednym :).
Załóżmy że executor i timeouter będą miały po 4 watki do dyspozycji.
Jeśli załóżmy timeout będzie leciał po 30 sekundach a to procesowanie w executorze będzie się w tle wykonywało np. 5 min to będzie taka sytuacja, że:

Wszystkie 4 wątki executora będą zajęte. Wszystkie 4 wątki tmeoutera będą wolne (zakładam, że już poszedł timeout).
No i wpada kolejny 5 RQ. Co w tedy się stanie? Czy on wpadnie na kolejkę do executora i będzie czekał na wolny wątek i pomimo tego, że timeouter zrobi timeout to prędzej czy później zostanie obsłużony?

Thx

Zobacz pozostały 1 komentarz
pedegie
Tak, po prostu później z kolejki zostanie zdjęty. Innymi słowy timeout ustawiany jest na "od wrzucenia do kolejki executora" a nie "od poczatku procesowania joba" - i taki efekt chyba chciałeś uzyskać bo perspektywa klienta jest ważna (że klient czeka 60 sek)
pedegie
no i timeouter może mieć 1 wątek - u niego też sie zakolejkuja joby a sama operacja result.completeExceptionally(new TimeoutException()) jest stosunkowo szybka wiec imho 1 wątek dla niego starczy. W Java 9 operator orTimeout korzysta z 1-go wątku (statyczny scheduler executor) dla wszystkich Futresów. EDIT: tam jest od 1 do MAX_INTEGER jednak, tak czy siak w tej sytuacji dałbym 1 wątek raczej - zależy czy przewidujecie tam jakieś peak'i że zakolejkuje sie kilkaset tego lub więcej, to można zwiększyć. Potestuj sobie curl'em
Charles_Ray
Jak dasz jeden wątek to będziesz w stanie obsłużyć tylko 1 request na minutę :)
pedegie
przy 1 wątku timeoutera? nie, 1 wątek timeouter'a może obsłużyć wiele wątków executora tego od jobów
pedegie
  • Rejestracja:około 11 lat
  • Ostatnio:ponad rok
  • Postów:204
1

Żeby nie kontyunować dyskusji w komentarzach to tutaj napiszę.

Jeden wątek timeouter'a może obsłużyć (czyli "ztajmałtować") wiele jobów, po prostu wraz z odkładaniem się zadań timeoutujących na kolejke, timeout'y kolejnych jobów będą rosły jeśli kolejka od jobów będzie zatkana ostro, weźmy ten kod z przykładu wyżej lekko zmodyfikowany żeby zasymulować tą sytuację:

Kopiuj
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.LockSupport;
import java.util.function.Consumer;

public class Test
{
    private static final ScheduledExecutorService timeouter = Executors.newSingleThreadScheduledExecutor();
    private static final ExecutorService executor = Executors.newFixedThreadPool(4);

    public static void main(String[] args)
    {
        long start = System.nanoTime();
        for(int i = 0; i < 5; i++)
        {
            test(result -> System.out.println(result + " in: " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " millis"));
        }

    }

    private static void test(Consumer<String> onFinishCallback)
    {
        CompletableFuture.supplyAsync(Test::someJob, executor)
                .applyToEither(timeoutAfter(2, TimeUnit.SECONDS), response -> response)
                .exceptionally(throwable -> "WARNING")
                        .thenAccept(onFinishCallback);
    }

    private static String someJob()
    {
        LockSupport.parkNanos((long) 5e9);
        System.out.println("PROCESSED");
        return "RESPONSE";
    }


    private static <T> CompletableFuture<T> timeoutAfter(long timeout, TimeUnit unit) {
        CompletableFuture<T> result = new CompletableFuture<T>();
        timeouter.schedule(() -> result.completeExceptionally(new TimeoutException()), timeout, unit);
        return result;
    }
}

To printluje:

Kopiuj
WARNING in: 2006 millis
WARNING in: 2019 millis
WARNING in: 2018 millis
WARNING in: 2018 millis
WARNING in: 2018 millis
PROCESSED
PROCESSED
PROCESSED
PROCESSED
PROCESSED

Zwiększmy i do 10, tak żeby nadal był 1 wątek timeouter'a, oraz zatkana kolejka executora od jobów, wynik będzie:

Kopiuj
WARNING in: 2005 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
PROCESSED
PROCESSED
PROCESSED
PROCESSED
PROCESSED
// tutaj przerwa w printlowaniu
PROCESSED
PROCESSED
PROCESSED
PROCESSED
PROCESSED

Podsumowując, na kolejce timeouter'a odkładają się job'y: result.completeExceptionally(new TimeoutException())

Założmy że odłożyliśmy takich 50 na raz, teraz pierwszy się wykona po 2 sekundach (w tym przykładzie, bo taki ustawliśmy timeout), kolejny po 2 sekundach i troszkę, kolejny po 2 sekundach i troszkę + troszkę etc

Przy i < 1000 wygląda to tak:

Kopiuj
WARNING in: 2006 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2024 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2025 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2026 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2027 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2028 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2029 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2030 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2031 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2032 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2033 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2034 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2035 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2036 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2037 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2038 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2039 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2040 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2041 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2042 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2043 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2044 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2045 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2046 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2047 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
WARNING in: 2048 millis
edytowany 5x, ostatnio: pedegie

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.