antfarm
Version:
File automation framework for ants.
445 lines (389 loc) • 10.4 kB
text/typescript
import { Tunnel } from "../tunnel/tunnel";
import { Nest } from "../nest/nest";
import {Environment} from "../environment/environment";
import {LifeEvent} from "../environment/lifeEvent";
import {EmailOptions} from "../environment/emailOptions";
import {JobProperty} from "./jobProperty";
// Handle the circular dependency by stashing the type in a variable for requiring later.
// import * as PackedJobTypes from "./packedJob";
// let PackedJob: typeof PackedJobTypes.PackedJob;
const shortid = require("shortid"),
_ = require("lodash");
export abstract class Job {
protected _name: string;
protected _tunnel: Tunnel;
protected _nest: Nest;
protected e: Environment;
protected _locallyAvailable: boolean;
protected _lifeCycle: LifeEvent[];
protected _id: string;
protected _properties;
protected _type: string;
/**
* Job constructor
* @param e
* @param name
*/
constructor(e: Environment, name: string) {
let j = this;
j.e = e;
j._id = shortid.generate();
j._name = name;
j._lifeCycle = [];
j._properties = {};
j._type = "base";
j.createLifeEvent("created", null, name);
j.e.log(1, `New Job "${name}" created, id: ${j.id}.`, j);
}
public get type() {
return this._type;
}
/**
* Class _name for logging.
* @returns {string}
*/
public toString() {
return "Job";
}
/**
* Check if job is locally available.
* @returns {boolean}
*/
public get isLocallyAvailable() {
return this._locallyAvailable;
}
/**
* Set if the job is locally available.
* @param available
*/
public set locallyAvailable(available: boolean) {
this._locallyAvailable = available;
}
/**
* Get the life cycle object.
* @returns {LifeEvent[]}
*/
public get lifeCycle() {
return this._lifeCycle;
}
public set lifeCycle(events: LifeEvent[]) {
this._lifeCycle = events;
}
/**
* Create a new life event.
* @param verb
* @param start
* @param finish
*/
protected createLifeEvent(verb: string, start: string, finish: string) {
this.lifeCycle.push(new LifeEvent(verb, start, finish));
}
/**
* Set a new _name.
* @param name
*/
public set name(name: string) {
this._name = name;
}
/**
* Get the _name.
* @returns {string}
*/
public get name() {
return this._name;
}
/**
* Get the ID.
* @returns {string}
*/
public get id() {
return this._id;
}
/**
* Get the _name proper.
* @returns {string}
*/
public get nameProper() {
return this.name;
}
/**
* Set the nest.
* @param nest
*/
public set nest(nest: Nest) {
this._nest = nest;
}
/**
* Get the nest.
* @returns {Nest}
*/
public get nest() {
return this._nest;
}
/**
* Set the tunnel.
* @param tunnel
*/
public set tunnel(tunnel: Tunnel) {
this._tunnel = tunnel;
}
/**
* Get the tunnel.
* @returns {Tunnel}
*/
public get tunnel() {
return this._tunnel;
}
/**
* Function to call to fail a job while in a tunnel.
* @param reason
*/
public fail(reason: string) {
let j = this;
if (!j.tunnel) {
j.e.log(3, `Job "${j.name}" failed before tunnel was set.`, j);
}
if (!j.nest) {
j.e.log(3, `Job "${j.name}" does not have a nest.`, j);
}
j.tunnel.executeFail(j, j.nest, reason);
}
/**
* Transfer a job to another tunnel directly.
* @param tunnel
*/
public transfer(tunnel: Tunnel) {
let job = this;
let oldTunnel = this.tunnel;
let oldTunnelName = "";
if (oldTunnel) {
oldTunnelName = oldTunnel.name;
}
job.tunnel = tunnel;
tunnel.arrive(job, null);
job.e.log(1, `Transferred to Tunnel "${tunnel.name}".`, job, [oldTunnel]);
job.createLifeEvent("transfer", oldTunnelName, tunnel.name);
}
/**
* Move function error.
*/
public move(destinationNest, callback) {
throw "This type of job cannot be moved.";
}
/**
* Sends an email.
* @param emailOptions Email options
* #### Sending pug template email example
* ```js
* // my_tunnel.js
* tunnel.run(function (job, nest) {
* job.email({
* subject: "Test email from pug template",
* to: "john.smith@example.com",
* template: __dirname + "./template_files/my_email.pug"
* });
* });
* ```
*
* ```js
* // template_files/my_email.pug
* h1="Example email!"
* p="Got job ID " + job.getId()
* ```
* #### Sending plain-text email
* ```js
* tunnel.run(function (job, nest) {
* job.email({
* subject: "Test email with hard-coded plain-text",
* to: "john.smith@example.com",
* text: "My email body!"
* });
* });
* ```
* #### Sending html email
* ```js
* tunnel.run(function (job, nest) {
* job.email({
* subject: "Test email with hard-coded html",
* to: "john.smith@example.com",
* html: "<h1>My email body!</h1>"
* });
* });
* ```
*/
public email(emailOptions: EmailOptions) {
let job = this;
let emailer = job.e.emailer;
emailer.sendMail(emailOptions, job);
}
/**
* Attach job specific data to the job instance.
* #### Example
*
* ```js
* job.setPropertyValue("My Job Number", 123456);
*
* console.log(job.getPropertyValue("My Job Number"));
* // 123456
* ```
*
* @param key
* @param value
*/
public setPropertyValue(key: string, value: any) {
let job = this;
let prop = new JobProperty(key, value);
job._properties[key] = prop;
job.e.log(1, `Property "${key}" added to job properties.`, job);
}
public set propertyValues(properties: Object) {
let job = this;
job._properties = properties;
job.e.log(0, `Restored ${Object.keys(job._properties).length} properties.`, job);
}
/**
* Get the entire job property object.
* @param key
* @returns {JobProperty}
*/
public getProperty(key: string) {
return this._properties[key] as JobProperty;
}
public get properties() {
return this._properties;
}
/**
* Get the value of a property if it has been previously set.
* @param key
* @returns {any}
*/
public getPropertyValue(key: string) {
let job = this;
if (job._properties[key]) {
return job._properties[key].value;
} else {
return null;
}
}
/**
* Get the type of a property.
* #### Example
*
* ```js
* job.setPropertyValue("My Job Number", 123456);
*
* console.log(job.getPropertyType("My Job Number"));
* // "number"
* ```
*
* @param key
* @returns {string}
*/
public getPropertyType(key: string) {
let job = this;
if (job._properties[key]) {
return job._properties[key].type;
} else {
return null;
}
}
/**
* Packs the job instance and file together in a zip.
* Returns a PackJob in the parameter of the callback.
* @param callback
* #### Example
* ```js
* job.pack(function(packJob){
* packJob.move(packed_folder_nest);
* });
* ```
*/
public pack(callback) {
let job = this;
let PackedJob = require("./packedJob").PackedJob;
let pj = new PackedJob(job.e, job);
pj.execPack(() => {
callback(pj);
});
}
/**
* Unpacks a packed job. Returns a the original unpacked job in the parameter of the callback.
* @param callback
* #### Example
* ```js
* packedJob.unpack(function(unpackedJob){
* console.log("Unpacked", unpackedJob.name);
* unpackedJob.move(unpacked_folder);
* packedJob.remove();
* });
* ```
*/
public unpack(callback) {
let job = this;
let PackedJob = require("./packedJob").PackedJob;
let pj = new PackedJob(job.e, job);
pj.execUnpack((unpackedJob) => {
callback(unpackedJob);
});
}
/**
* Get the job object as JSON with circular references removed.
* @returns {string}
*/
public getJSON() {
let job = this;
let json;
let replacer = function(key, value) {
// Filtering out properties
if (key === "nest" || key === "e" || key === "tunnel") {
return undefined;
}
if (key === "_nest" || key === "_tunnel") {
return undefined;
}
return value;
};
try {
json = JSON.stringify(job, replacer);
} catch (err) {
job.e.log(3, `getJSON stringify error: ${err}`, job);
}
return json;
}
public get path() {
return undefined;
}
public isFile() {
return undefined;
}
public isFolder() {
return undefined;
}
public get files() {
return undefined;
}
public getFile(index: any) {
return undefined;
}
public set path(path: string) {
}
public rename(name: string) {
return undefined;
}
/**
* Add a message to the log with this job as the actor.
* @param level 0 = debug, 1 = info, 2, = warning, 3 = error
* @param message Log message
* @returns {undefined}
*/
public log(level: number, message: string) {
let job = this;
return job.e.log(level, message, job);
}
public get size () {
return undefined;
}
public get sizeBytes () {
return undefined;
}
}