io.stallion.slowTests.AsyncTaskSlowTests.java Source code

Java tutorial

Introduction

Here is the source code for io.stallion.slowTests.AsyncTaskSlowTests.java

Source

/*
 * Stallion Core: A Modern Web Framework
 *
 * Copyright (C) 2015 - 2016 Stallion Software LLC.
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation, either version 2 of
 * the License, or (at your option) any later version. This program is distributed in the hope that
 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 * License for more details. You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
 *
 *
 *
 */

package io.stallion.slowTests;

import io.stallion.Context;
import io.stallion.asyncTasks.AsyncCoordinator;
import io.stallion.asyncTasks.AsyncFileCoordinator;
import io.stallion.asyncTasks.AsyncTask;
import io.stallion.asyncTasks.AsyncTaskController;
import io.stallion.fileSystem.FileSystemWatcherService;
import io.stallion.services.Log;
import io.stallion.testing.AppIntegrationCaseBase;
import io.stallion.utils.DateUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Date;

import static io.stallion.utils.Literals.*;

public class AsyncTaskSlowTests extends AppIntegrationCaseBase {

    @BeforeClass
    public static void setUpClass() throws Exception {
        startApp("/a_minimal_site", true);
        AsyncCoordinator.shutDownForTests();
        File tasksDir = new File(Context.getSettings().getDataDirectory() + "/async-tasks");
        if (tasksDir.isDirectory()) {
            FileUtils.deleteDirectory(tasksDir);
        }
        FileSystemWatcherService.start();
        AsyncCoordinator.initAndStart();
        AsyncCoordinator.instance().registerClassLoader(AsyncTaskSlowTests.class.getClassLoader());
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
        AsyncCoordinator.gracefulShutdown();
        cleanUpClass();
    }

    public void testLoadFromManualEntries() throws IOException, InterruptedException {
        AsyncFileCoordinator coordinator = (AsyncFileCoordinator) AsyncCoordinator.instance();
        // Leave time for the watcher to start running
        Thread.sleep(200);
        String taskJson = "{\n" + "  \"deleted\" : false,\n" + "  \"isNewInsert\" : false,\n"
                + "  \"createdAt\" : 0,\n" + "  \"updatedAt\" : 0,\n"
                + "  \"handlerName\" : \"io.stallion.slowTests.ExampleTaskHandler\",\n"
                + "  \"customKey\" : \"\",\n" + "  \"lockedAt\" : 1421371349577,\n"
                + "  \"failedAt\" : 1421371349577,\n" + "  \"completedAt\" : 0,\n"
                + "  \"originallyScheduledFor\" : 0,\n" + "  \"executeAt\" : 1921371332731,\n"
                + "  \"neverRetry\" : false,\n" + "  \"lockUuid\" : null,\n" + "  \"secret\" : null,\n"
                + "  \"tryCount\" : 5,\n" + "  \"errorMessage\" : null,\n"
                + "  \"dataJson\" : \"{\\n  \\\"myKey\\\" : \\\"myVal\\\",\\n  \\\"taskNumber\\\" : 0\\n}\",\n"
                + "  \"id\" : 1001\n" + "}";
        File taskFile = new File(Context.getSettings().getDataDirectory()
                + "/async-tasks/manualRetry/2015-01-16-0122-1273-ExampleTaskHandler-1421371347569-937506272.json");
        FileUtils.write(taskFile, taskJson, UTF8);
        for (int t = 0; t < 100; t++) {
            if (!taskFile.isFile() && coordinator.hasTaskWithId(1001L)) {
                break;
            }
            Thread.sleep(100);
        }
        Assert.assertTrue(!taskFile.isFile());
        Assert.assertTrue(coordinator.hasTaskWithId(1001L));

    }

    @Test
    public void testLoadAfterRestart() throws InterruptedException {
        AsyncFileCoordinator coordinator = (AsyncFileCoordinator) AsyncCoordinator.instance();
        String myKey = "futureKey-" + new Date().getTime();
        AsyncTask task = AsyncCoordinator.instance().enqueue(new ExampleTaskHandler().setMyKey(myKey),
                "custom-keyz-future", 1921371347569L);
        Assert.assertTrue(coordinator.hasTaskWithId(task.getId()));

        coordinator.getTaskQueue().clear();
        Assert.assertFalse(coordinator.instance().hasTaskWithId(task.getId()));

        AsyncTaskController.instance().reset();

        for (int x = 0; x < 20; x++) {
            if (coordinator.instance().hasTaskWithId(task.getId())) {
                break;
            }
            Thread.sleep(10);
        }
        Assert.assertTrue(coordinator.instance().hasTaskWithId(task.getId()));

    }

    public void testFlow() throws Exception {
        AsyncCoordinator coordinator = AsyncCoordinator.instance();

        // Create 20 tasks, the first 10 to be executed now, 9 to be executed within the next 2 seconds, 1 to be executed far in the future
        for (int x = 1; x < 21; x++) {
            long executeAt = 0;
            String customKey = "";
            if (x % 2 == 0) {
                executeAt = DateUtils.mils() + (x * 100);
                customKey = "custom-key-" + x;
            }
            if (x == 18) {
                executeAt = DateUtils.mils() + 99999999;
            }
            AsyncTask task = new AsyncTask(new ExampleTaskHandler().setMyKey("myVal").setTaskNumber(x), customKey,
                    executeAt);
            task.enqueue();
        }

        // Reschedule task 0 for the far future
        Log.info("Reschedule 6 for the far future");
        AsyncTask futureDated = new AsyncTask(new ExampleTaskHandler().setMyKey("myVal").setTaskNumber(0),
                "custom-key-6", DateUtils.mils() + 1111112500);
        futureDated.enqueue();

        // Update task 17 with a new myKey
        Log.info("Update task 2 with a new myKey value");
        AsyncTask updated = new AsyncTask(new ExampleTaskHandler().setMyKey("anUpdatedValueFor2").setTaskNumber(2),
                "custom-key-2", DateUtils.mils() + 800);
        updated.enqueue();

        Assert.assertEquals(20, coordinator.getPendingTaskCount());

        Log.info(
                "Sleep for 3 seconds, all tasks should complete, except for 18 and 19 and, because those were future dated");
        Thread.sleep(5000);

        // Was always scheduled for the far future
        Assert.assertTrue(!ExampleTaskHandler.handledTaskNumbers.contains(18));
        // Was rescheduled for the future
        Assert.assertTrue(!ExampleTaskHandler.handledTaskNumbers.contains(0));
        // Got an updated key
        Assert.assertTrue(ExampleTaskHandler.handledMyKeys.contains("anUpdatedValueFor2"));
        // 20 tasks, minus the two that were way future dated
        Assert.assertEquals(18, ExampleTaskHandler.handledCount.get());

        //// PART II ///////////////////////

        // Duplicate customKey, this task will be ignored
        AsyncTask duplicate = new AsyncTask(new ExampleTaskHandler().setMyKey("myVal14Duplicate").setTaskNumber(14),
                "custom-key-14", DateUtils.mils());
        duplicate.enqueue();

        // Lock checking task that then fails
        AsyncTask checkingTask = new AsyncTask(new LockAndErrorCheckingTaskHandler());
        checkingTask.setTryCount(99); // Won't retry when fails
        checkingTask.enqueue();

        // Still should be 18 tasks, the duplicate custom key task should have been ignored
        Thread.sleep(2000);
        Assert.assertEquals(18, ExampleTaskHandler.handledCount.get());
        Assert.assertTrue(!ExampleTaskHandler.handledMyKeys.contains("myVal15Duplicate"));

        // Locked file was found while running tasks
        Assert.assertTrue(LockAndErrorCheckingTaskHandler.lockFileFound);

        File completedFolder = new File(Context.getSettings().getDataDirectory() + "/async-tasks/completed");
        File lockedFolder = new File(Context.getSettings().getDataDirectory() + "/async-tasks/locked");
        File failedFolder = new File(Context.getSettings().getDataDirectory() + "/async-tasks/failed");
        File pendingFolder = new File(Context.getSettings().getDataDirectory() + "/async-tasks/pending");

        // 18 completed tasks should be in the completed folder
        FileFilter fileFilter = new RegexFileFilter("\\d+.*\\.json");
        Assert.assertEquals(18, completedFolder.listFiles(fileFilter).length);

        // 2 tasks should be in the pending folder
        Assert.assertEquals(2, pendingFolder.listFiles(fileFilter).length);

        // 0 tasks in the locked folder
        Assert.assertEquals(0, lockedFolder.listFiles(fileFilter).length);

        // 1 tasks in the failed folder
        Assert.assertEquals(1, failedFolder.listFiles(fileFilter).length);

    }

}