Skip to content

Commit

Permalink
Merge pull request #97 from HahaBill/f/mindsdb-create-job
Browse files Browse the repository at this point in the history
[Hacktoberfest] Job functionality
  • Loading branch information
setohe0909 authored Nov 6, 2024
2 parents d5f75f6 + b79ca1f commit fc7af53
Show file tree
Hide file tree
Showing 5 changed files with 310 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import DatabasesModule from './databases/databasesModule';
import ProjectsModule from './projects/projectsModule';
import SQLModule from './sql/sqlModule';
import ViewsModule from './views/viewsModule';
import JobsModule from './jobs/jobsModule';
import Constants from './constants';
import {
createDefaultAxiosInstance,
Expand Down Expand Up @@ -51,6 +52,7 @@ const Projects = new ProjectsModule.ProjectsRestApiClient(
);
const Tables = new TablesModule.TablesRestApiClient(SQL);
const Views = new ViewsModule.ViewsRestApiClient(SQL);
const Jobs = new JobsModule.JobsRestApiClient(SQL);
const MLEngines = new MLEnginesModule.MLEnginesRestApiClient(
SQL,
defaultAxiosInstance,
Expand Down Expand Up @@ -116,6 +118,7 @@ export default {
Projects,
Tables,
Views,
Jobs,
MLEngines,
Callbacks,
};
Expand Down
139 changes: 139 additions & 0 deletions src/jobs/job.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import JobsApiClient from './jobsApiClient';
import { MindsDbError } from '../errors';

/**
* Represents a MindsDB job and provides methods to build and create it.
*/
export default class Job {
/** API client to use for executing job operations. */
private jobsApiClient: JobsApiClient;

/** Name of the job. */
name: string;

/** Project the job belongs to. */
project: string;

/** Accumulated queries to be executed by the job. */
private queries: string[];

/** Optional start date for the job. */
private start?: string;

/** Optional end date for the job. */
private end?: string;

/** Optional repetition frequency. */
private every?: string;

/** Optional condition for job execution. */
private ifCondition?: string;

/**
* @param {JobsApiClient} jobsApiClient - API client to use for executing job operations.
* @param {string} name - Name of the job.
* @param {string} project - Project the job belongs to.
*/
constructor(jobsApiClient: JobsApiClient, name: string, project: string) {
this.jobsApiClient = jobsApiClient;
this.name = name;
this.project = project;
this.queries = [];
}

/**
* Adds a query to the job.
* @param {string} query - The query to add.
* @returns {Job} - The current job instance (for chaining).
* @throws {MindsDbError} - If the query is invalid.
*/
addQuery(query: string): Job {
if (typeof query === 'string') {
this.queries.push(query);
} else {
throw new MindsDbError('Invalid query type. Must be a string.');
}
return this;
}

/**
* Sets the start date for the job.
* @param {string} start - The start date as a string.
* @returns {Job} - The current job instance (for chaining).
*/
setStart(start: string): Job {
this.start = start;
return this;
}

/**
* Sets the end date for the job.
* @param {string} end - The end date as a string.
* @returns {Job} - The current job instance (for chaining).
*/
setEnd(end: string): Job {
this.end = end;
return this;
}

/**
* Sets the repetition frequency for the job.
* @param {string} every - The repetition frequency.
* @returns {Job} - The current job instance (for chaining).
*/
setEvery(every: string): Job {
this.every = every;
return this;
}

/**
* Sets the condition for job execution.
* @param {string} ifCondition - The condition as a string.
* @returns {Job} - The current job instance (for chaining).
*/
setIfCondition(ifCondition: string): Job {
this.ifCondition = ifCondition;
return this;
}

/**
* Creates the job in MindsDB.
* @returns {Promise<void>} - Resolves when the job is created.
* @throws {MindsDbError} - If job creation fails.
*/
async createJob(): Promise<void> {
if (this.queries.length === 0) {
throw new MindsDbError('No queries added to the job.');
}
const queryStr = this.queries.join(';\n');
await this.jobsApiClient.createJob(
this.name,
this.project,
queryStr,
this.start,
this.end,
this.every,
this.ifCondition
);
}

/**
* Deletes the job from MindsDB.
* @returns {Promise<void>} - Resolves when the job is deleted.
* @throws {MindsDbError} - If job deletion fails.
*/
async deleteJob(): Promise<void> {
await this.jobsApiClient.deleteJob(this.name, this.project);
}

/**
* Drops (deletes) a job from MindsDB by name.
* @param {string} name - Name of the job to drop.
* @param {string} project - Project the job belongs to.
* @returns {Promise<void>} - Resolves when the job is dropped.
* @throws {MindsDbError} - Something went wrong while dropping the job.
*/
async dropJob(name: string, project: string = "mindsdb"): Promise<void> {
await this.jobsApiClient.dropJob(name, project);
}
}
57 changes: 57 additions & 0 deletions src/jobs/jobsApiClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Job from './job';

/**
* Abstract class outlining Job API operations supported by the SDK.
*/
export default abstract class JobsApiClient {
/**
* Creates a new Job instance for building and creating a job.
* @param {string} name - Name of the job.
* @param {string} project - Project the job belongs to.
* @returns {Job} - A new Job instance.
*/
abstract create(name: string, project: string): Job;

/**
* Internal method to create the job in MindsDB.
* @param {string} name - Name of the job to create.
* @param {string} project - Project the job will be created in.
* @param {string} query - Queries to be executed by the job.
* @param {string} [start] - Optional start date for the job.
* @param {string} [end] - Optional end date for the job.
* @param {string} [every] - Optional repetition frequency.
* @param {string} [ifCondition] - Optional condition for job execution.
* @returns {Promise<void>} - Resolves when the job is created.
* @throws {MindsDbError} - Something went wrong while creating the job.
*/
abstract createJob(
name: string,
project: string,
query: string,
start?: string,
end?: string,
every?: string,
ifCondition?: string
): Promise<void>;

/**
* Internal method to delete the job in MindsDB.
* @param {string} name - Name of the job to delete.
* @param {string} project - Project the job will be deleted.
* @returns {Promise<void>} - Resolves when the job is deleted.
* @throws {MindsDbError} - Something went wrong while deleting the job.
*/
abstract deleteJob(
name: string,
project: string
): Promise<void>

/**
* Drops (deletes) a job from MindsDB by name.
* @param {string} name - Name of the job to drop.
* @param {string} project - Project the job belongs to.
* @returns {Promise<void>} - Resolves when the job is dropped.
* @throws {MindsDbError} - Something went wrong while dropping the job.
*/
abstract dropJob(name: string, project: string): Promise<void>;
}
3 changes: 3 additions & 0 deletions src/jobs/jobsModule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import JobsRestApiClient from './jobsRestApiClient';

export default { JobsRestApiClient };
108 changes: 108 additions & 0 deletions src/jobs/jobsRestApiClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import mysql from 'mysql';
import { MindsDbError } from '../errors';

import SqlApiClient from '../sql/sqlApiClient';
import Job from './job';
import JobsApiClient from './jobsApiClient';

export default class JobsRestApiClient extends JobsApiClient {
sqlClient: SqlApiClient;

/**
* @param {SqlApiClient} sqlClient - SQL API client to send all SQL query requests.
*/
constructor(sqlClient: SqlApiClient) {
super();
this.sqlClient = sqlClient;
}

/**
* Creates a new Job instance for building and creating a job.
* @param {string} name - Name of the job.
* @param {string} project - Project the job belongs to.
* @returns {Job} - A new Job instance.
*/
override create(name: string, project: string = "mindsdb"): Job {
return new Job(this, name, project);
}

/**
* Internal method to create the job in MindsDB.
* @param {string} name - Name of the job to create.
* @param {string} project - Project the job will be created in.
* @param {string} query - Queries to be executed by the job.
* @param {string} [start] - Optional start date for the job.
* @param {string} [end] - Optional end date for the job.
* @param {string} [every] - Optional repetition frequency.
* @param {string} [ifCondition] - Optional condition for job execution.
* @returns {Promise<void>} - Resolves when the job is created.
* @throws {MindsDbError} - Something went wrong while creating the job.
*/
override async createJob(
name: string,
project: string,
query: string,
start?: string,
end?: string,
every?: string,
ifCondition?: string
): Promise<void> {
let createJobQuery = `CREATE JOB ${mysql.escapeId(project)}.${mysql.escapeId(name)} (\n${query}\n)`;

if (start) {
createJobQuery += `\nSTART '${start}'`;
}
if (end) {
createJobQuery += `\nEND '${end}'`;
}
if (every) {
createJobQuery += `\nEVERY ${every}`;
}
if (ifCondition) {
createJobQuery += `\nIF (\n${ifCondition}\n)`;
}

const sqlQueryResult = await this.sqlClient.runQuery(createJobQuery);
if (sqlQueryResult.error_message) {
throw new MindsDbError(sqlQueryResult.error_message);
}
}

/**
* Internal method to delete the job in MindsDB.
* @param {string} name - Name of the job to delete.
* @param {string} project - Project the job belongs to.
* @returns {Promise<void>} - Resolves when the job is deleted.
* @throws {MindsDbError} - Something went wrong while deleting the job.
*/
override async deleteJob(
name: string,
project: string
): Promise<void> {
const dropJobQuery = `DROP JOB ${mysql.escapeId(project)}.${mysql.escapeId(name)};`;

const sqlQueryResult = await this.sqlClient.runQuery(dropJobQuery);
if (sqlQueryResult.error_message) {
throw new MindsDbError(sqlQueryResult.error_message);
}
}

/**
* Internal method to deleting the job in MindsDB with users providing a name
* @param {string} name - Name of the job to delete.
* @param {string} project - Project the job belongs to.
* @returns {Promise<void>} - Resolves when the job is deleted.
* @throws {MindsDbError} - Something went wrong while deleting the job.
*/
override async dropJob(
name: string,
project: string = "mindsdb"
): Promise<void> {
const dropJobQuery = `DROP JOB ${mysql.escapeId(project)}.${mysql.escapeId(name)};`;

const sqlQueryResult = await this.sqlClient.runQuery(dropJobQuery);
if (sqlQueryResult.error_message) {
throw new MindsDbError(sqlQueryResult.error_message);
}
}
}

0 comments on commit fc7af53

Please sign in to comment.