001/* 002 * Stallion Core: A Modern Web Framework 003 * 004 * Copyright (C) 2015 - 2016 Stallion Software LLC. 005 * 006 * This program is free software: you can redistribute it and/or modify it under the terms of the 007 * GNU General Public License as published by the Free Software Foundation, either version 2 of 008 * the License, or (at your option) any later version. This program is distributed in the hope that 009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 011 * License for more details. You should have received a copy of the GNU General Public License 012 * along with this program. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>. 013 * 014 * 015 * 016 */ 017 018package io.stallion.asyncTasks; 019 020import io.stallion.Context; 021import io.stallion.dataAccess.DataAccessRegistration; 022import io.stallion.dataAccess.StandardModelController; 023import io.stallion.dataAccess.NoStash; 024import io.stallion.dataAccess.db.DB; 025 026import java.util.HashSet; 027import java.util.Set; 028 029import static io.stallion.utils.Literals.*; 030 031 032public class AsyncTaskController extends StandardModelController<AsyncTask> { 033 protected static final String BUCKET_NAME = "async_tasks"; 034 protected static final String PATH_NAME = "async-tasks"; 035 protected static final String TABLE_NAME = "stallion_async_tasks"; 036 037 private static Set<String> _keyFields; 038 039 static { 040 _keyFields = new HashSet<>(); 041 _keyFields.add("customKey"); 042 } 043 044 public static AsyncTaskController instance() { 045 return (AsyncTaskController) Context.dal().get(BUCKET_NAME); 046 } 047 048 public static void register() { 049 if (DB.available()) { 050 registerDbBased(); 051 } else { 052 registerFileBased(); 053 } 054 } 055 056 057 058 public static void registerDbBased() { 059 DataAccessRegistration registration = new DataAccessRegistration() 060 .setControllerClass(AsyncTaskController.class) 061 .setModelClass(AsyncTask.class) 062 .setBucket(BUCKET_NAME) 063 .setTableName(TABLE_NAME) 064 .setPersisterClass(AsyncTaskDbPersister.class) 065 .setStashClass(NoStash.class) 066 .setWritable(true); 067 Context.dal().register(registration); 068 } 069 070 071 public static void registerFileBased() { 072 DataAccessRegistration registration = new DataAccessRegistration() 073 .setControllerClass(AsyncTaskController.class) 074 .setModelClass(AsyncTask.class) 075 .setBucket(BUCKET_NAME) 076 .setPath(PATH_NAME) 077 .setPersisterClass(AsyncTaskFilePersister.class) 078 .setWritable(true) 079 .setShouldWatch(true) 080 .setUseDataFolder(true); 081 082 Context.dal().register(registration); 083 } 084 085 /** Registers an ephemeral version of the controller that will not actually store tasks to files. 086 * Used for unittests when we don't want to store the tasks 087 */ 088 public static void registerEphemeral() { 089 DataAccessRegistration registration = new DataAccessRegistration() 090 .setControllerClass(AsyncTaskController.class) 091 .setModelClass(AsyncTask.class) 092 .setPath(PATH_NAME) 093 .setBucket(BUCKET_NAME) 094 .setPersisterClass(DummyTaskPersister.class) 095 .setShouldWatch(false) 096 .setUseDataFolder(false) 097 .setWritable(true); 098 Context.dal().register(registration); 099 } 100 101 102 103 104 /** 105 * This gets called when we restart the application and reload all the tasks from the /pending folder 106 * @param task 107 */ 108 public void onPostLoadItem(AsyncTask task) { 109 AsyncCoordinator.instance().onLoadTaskOnBoot(task); 110 } 111 112 113 114 115 116 117 public TaskHealthInfo buildHealthInfo() { 118 TaskHealthInfo info = new TaskHealthInfo(); 119 info.setPendingTasks(AsyncCoordinator.instance().getPendingTaskCount()); 120 //info.setCompletedTasks(seenTaskIds.size()); 121 Long thirtyAgo = mils() - 30 * 60 * 1000; 122 info.setStuckTasks(filterChain().filter("originallyScheduledFor", thirtyAgo, "<").filter("completedAt", 0L).count()); 123 return info; 124 } 125 126 127 128 @Override 129 public Set<String> getUniqueFields() { 130 return _keyFields; 131 } 132 133 @Override 134 public void reset() { 135 super.reset(); 136 } 137 138 139 140}