All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.simplity.job.JobsManager Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2017 simplity.org
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package org.simplity.job;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.simplity.kernel.Application;
import org.simplity.kernel.Messages;
import org.simplity.kernel.data.DataSheet;
import org.simplity.kernel.data.MultiRowsSheet;
import org.simplity.kernel.db.DbDriver;
import org.simplity.kernel.value.Value;
import org.simplity.service.AbstractService;
import org.simplity.service.ServiceContext;
import org.simplity.tp.LogicInterface;

/**
 * Example of a class that implements a full service
 *
 * @author simplity.org
 *
 */
public class JobsManager extends AbstractService implements LogicInterface {
	private static final String MY_NAME = "JobsManager";

	/*
	 * field names
	 */
	private static final String ACTION = "jobsAction";
	private static final String JOB_NAME = "jobName";
	private static final String JOBS_NAME = "jobsName";
	private static final String INTERVAL = "interval";
	private static final String NBR_THREADS = "nbrThreads";
	private static final String SERVICE_NAME = "serviceName";
	private static final String RUN_AT_THESE_TIMES = "runAtTheseTimes";
	/*
	 * valid actions/commands
	 */
	private static final String START = "start";
	private static final String STOP = "stop";
	private static final String INCR = "incr";
	private static final String DECR = "decr";
	private static final String STATUS = "status";
	private static final String CANCEL = "cancel";
	private static final String SCHEDULE = "schedule";
	private static final String NEW = "new";
	private static final String USAGE = "USAGE\nstart JobsName  : start a pre-defined Jobs\n"
			+ "start : start a blank Jobs to which you can add jobs with action=new\n"
			+ "stop : stop and unload current Jobs\n" + "status : get status of all jobs\n"
			+ "status jobName : get status of this job\n"
			+ "cancel jobName : cancel/stop/unschedule/interrupt this job\n "
			+ "new jobName    : (provide one of the three params) add a new job and schedule it."
			+ "schedule jobName : reschedule a job that was previousy cancelled";

	/*
	 * others
	 */
	private static final String SHEET_NAME = "jobsInfo";
	private static final String FIELD_SEP = ", ";
	private static final String ROW_SEP_SEP = "\n";

	/*
	 * (non-Javadoc)
	 *
	 * @see org.simplity.kernel.comp.Component#getSimpleName()
	 */
	@Override
	public String getSimpleName() {
		return MY_NAME;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.simplity.kernel.comp.Component#getQualifiedName()
	 */
	@Override
	public String getQualifiedName() {
		return MY_NAME;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.simplity.service.ServiceInterface#executeAsAction(org.simplity.
	 * service
	 * .ServiceContext, org.simplity.kernel.db.DbDriver)
	 */
	@Override
	public Value executeAsAction(ServiceContext ctx, DbDriver driver, boolean transactionIsdelegated) {

		String action = ctx.getTextValue(ACTION);
		if (action == null || action.isEmpty()) {
			ctx.addMessage(Messages.ERROR, USAGE);
			return Value.VALUE_FALSE;
		}
		String JobsName = ctx.getTextValue(JOBS_NAME);
		/*
		 * we make use of the default input-output in AbstractService and put
		 * our logic here, so that we can also be called by other services
		 */
		Jobs jobs = Jobs.getCurrentInstance();

		/*
		 * when no Jobs is running
		 */
		if (jobs == null) {
			if (action.equals(START)) {
				if (JobsName == null || JobsName.isEmpty()) {
					jobs = Jobs.startEmptyJobs();
				} else {
					jobs = Jobs.startJobs(JobsName);
				}
				if (jobs == null) {
					ctx.addMessage(Messages.ERROR, "Jobs could not be started. Look at logs for more details..");
				} else {
					ctx.addMessage(Messages.SUCCESS, "Jobs started");
				}
			} else {
				if (action.equals(STATUS) == false) {
					ctx.addMessage(Messages.ERROR, "No Jobs is running. Use start action to start  a Jobs.");
				}
			}

		} else if (action.equals(STATUS) == false) {
			this.takeAction(jobs, action, ctx);
			if (action.equals(STOP)) {
				jobs = null;
			}
		}

		if (jobs == null) {
			ctx.removeValue(JOBS_NAME);
		} else {
			ctx.setTextValue(JOBS_NAME, jobs.getQualifiedName());
			RunningJobInfo[] infoList = jobs.getStatus();
			DataSheet ds = RunningJobInfo.toDataSheet(infoList);
			ctx.putDataSheet(SHEET_NAME, ds);
		}
		/*
		 * we always provide status
		 */
		return null;

	}

	private void takeAction(Jobs Jobs, String action, ServiceContext ctx) {
		String jobName = ctx.getTextValue(JOB_NAME);
		if (action.equals(START)) {
			ctx.addMessage(Messages.ERROR, "A scheduler is running. Can not start another one");
			return;
		}

		if (action.equals(STOP)) {
			ctx.addMessage(Messages.INFO, "Initiated shutdown for job " + jobName);
			Jobs.stopJobs();
			ctx.removeValue(JOBS_NAME);
			return;
		}

		if (jobName == null) {
			ctx.addMessage(Messages.VALUE_REQUIRED, JOB_NAME);
			return;
		}

		if (action.equals(CANCEL)) {
			Jobs.cancelJob(jobName);
			ctx.addMessage(Messages.INFO, "Initiated shutdown for job " + jobName);
			return;
		}
		if (action.equals(INCR)) {
			Jobs.incrmentThread(jobName);
			ctx.addMessage(Messages.INFO, "Initiated addition of a thread for job " + jobName);
			return;
		}
		if (action.equals(DECR)) {
			Jobs.decrmentThread(jobName);
			ctx.addMessage(Messages.INFO, "Initiated stopping of a thread for job " + jobName);
			return;
		}
		if (action.equals(SCHEDULE)) {
			Jobs.reschedule(jobName);
			ctx.addMessage(Messages.INFO, "Initiated stestart of job " + jobName);
			return;
		}

		if (action.equals(NEW)) {
			String serviceName = ctx.getTextValue(SERVICE_NAME);
			if (serviceName == null) {
				ctx.addMessage(Messages.VALUE_REQUIRED, SERVICE_NAME);
				return;
			}
			String times = ctx.getTextValue(RUN_AT_THESE_TIMES);
			int nbrThreads = (int) ctx.getLongValue(NBR_THREADS);
			int interval = (int) ctx.getLongValue(INTERVAL);
			Job job = new Job(jobName, serviceName, interval, nbrThreads, times);
			job.getReady();
			ctx.addMessage(Messages.INFO, "added job " + jobName + " to scheduler..");
			Jobs.scheduleJob(job);
			return;
		}
		ctx.addMessage(Messages.ERROR, action + " is an invalid action " + USAGE);
		return;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.simplity.tp.LogicInterface#execute(org.simplity.service.
	 * ServiceContext)
	 */
	@Override
	public Value execute(ServiceContext ctx) {
		return this.executeAsAction(ctx, null, false);
	}

	/**
	 *
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		String path = "c:/repos/simplity/test/WebContent/WEB-INF/comp/";
		if (args.length > 0) {
			path = args[0];
		}
		Application.bootStrap(path);
		System.out.println("Probably start is the best way to start :-)");
		String action = null;
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		JobsManager manager = new JobsManager();
		ServiceContext ctx;
		String sn = "unknown";
		Value userId = Value.newTextValue("420");
		while (true) {
			System.out.print(ACTION + "[enter to exit] :");
			action = reader.readLine();
			if (action == null) {
				System.out.print("Bye..");
				break;
			}
			action.trim();
			if (action.isEmpty()) {
				System.out.print("Bye..");
				break;
			}
			System.out.println("Going to process action " + action);
			ctx = new ServiceContext(sn, userId);
			ctx.setTextValue(ACTION, action);
			action = action.toLowerCase();
			if (action.equals(START)) {
				getInput(reader, JOBS_NAME, ctx, false);
			} else if (action.equals(STATUS)) {
				getInput(reader, JOB_NAME, ctx, false);
			} else if (action.equals(STOP)) {
				//
			} else {
				getInput(reader, JOB_NAME, ctx, false);

				if (action.equals(NEW)) {
					getInput(reader, SERVICE_NAME, ctx, false);
					getInput(reader, INTERVAL, ctx, true);
					getInput(reader, NBR_THREADS, ctx, true);
					getInput(reader, RUN_AT_THESE_TIMES, ctx, false);
				}
			}
			manager.executeAsAction(ctx, null, false);

			MultiRowsSheet ds = (MultiRowsSheet) ctx.getMessagesAsDs();
			if (ds.length() > 0) {
				System.out.println("Messages");
				System.out.println(ds.toString(FIELD_SEP, ROW_SEP_SEP));
			}
			ds = (MultiRowsSheet) ctx.getDataSheet(SHEET_NAME);
			if (ds != null && ds.length() > 0) {
				System.out.println("Status");
				System.out.println(ds.toString(FIELD_SEP, ROW_SEP_SEP));
			}
		}
	}

	private static void getInput(BufferedReader reader, String name, ServiceContext ctx, boolean isNumber)
			throws IOException {
		System.out.print(name + "[enter to skip] :");
		String value = reader.readLine();
		if (value == null) {
			return;
		}
		value = value.trim();
		if (value.isEmpty()) {
			return;
		}

		if (isNumber == false) {
			ctx.setTextValue(name, value);
			return;
		}
		long n = 0;
		try {
			n = Long.parseLong(value);
		} catch (Exception e) {
			System.out.println(value + " is an invalid number. 0 assumed.");
		}
		ctx.setLongValue(name, n);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy