Skip to content

Commit

Permalink
Merge pull request #6 from Climactic/feat/cancel-jobs
Browse files Browse the repository at this point in the history
feat: cancel jobs
  • Loading branch information
adiologydev authored Sep 3, 2024
2 parents aade6d0 + 0862116 commit f21cfb4
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 9 deletions.
8 changes: 8 additions & 0 deletions .changeset/green-jars-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"tinyjobs": patch
"@tinyjobs/cli": patch
---

fix(cli): support non-args jobs
feat(tinyjobs): add support for canceling jobs
chore: better readme
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ export default class FirstJob extends Job {
}
```


## Roadmap
TinyJobs is not feature complete and still in early stages, you can refer to the roadmap for the list of currently planend features and their progress [here](https://github.com/orgs/Climactic/projects/1/views/4).


## Develop

To develop all apps and packages, run the following command:
Expand Down
16 changes: 12 additions & 4 deletions apps/example/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,22 @@ const tinyJobs = new TinyJobs<TinyJobsTypes>({
await tinyJobs.loadJobs();

// Run Jobs which are not scheduled via cron
tinyJobs.invoke("exampleJob", { name: "exampleJob" });
tinyJobs.invoke("delayedJob", { name: "DelayedJob" });
const cancelJobId = await tinyJobs.invoke("cancelExample");
await tinyJobs.invoke("exampleJob", { name: "exampleJob" });
await tinyJobs.invoke("delayedJob", { name: "DelayedJob" });

// Cancel a job
tinyJobs.cancel("cancelExample", cancelJobId);

// Logging
tinyJobs.events.on(TinyJobEvents.JOB_COMPLETE, (job) => {
console.log(job);
console.log("[COMPLETED]\n", job);
});

tinyJobs.events.on(TinyJobEvents.JOB_FAILED, (job) => {
console.error(job);
console.error("[FAILED]\n", job);
});

tinyJobs.events.on(TinyJobEvents.JOB_CANCELLED, (job) => {
console.log("[CANCELLED]\n", job);
});
15 changes: 15 additions & 0 deletions apps/example/src/jobs/CancelExample.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { sleep } from "bun";
import { Job } from "tinyjobs";

export default class CancelExample extends Job {
constructor() {
super({
name: "cancelExample",
delay: 50000,
});
}

async run() {
sleep(100000);
}
}
2 changes: 2 additions & 0 deletions apps/example/src/jobs/jobs.types.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
interface cancelExampleParams {};
interface cronExampleParams { name: string };
interface delayedJobParams { name: string };
interface exampleJobParams { name: string };

type TinyJobsTypes = {
'cancelExample': cancelExampleParams;
'cronExample': cronExampleParams;
'delayedJob': delayedJobParams;
'exampleJob': exampleJobParams
Expand Down
8 changes: 6 additions & 2 deletions packages/cli/src/commands/generate/generateTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { log } from "@clack/prompts";

interface JobTypeDefinition {
jobName: string;
paramsType: string;
paramsType?: string;
}

function extractJobTypes(filePath: string): JobTypeDefinition | null {
Expand Down Expand Up @@ -63,13 +63,17 @@ function extractJobTypes(filePath: string): JobTypeDefinition | null {
const param = member.parameters[0];
if (param && param.type) {
paramsType = param.type.getFullText().trim();
} else {
// If no parameters, set paramsType to an empty object type
paramsType = "{}";
}
}
});
}
});

if (jobName && paramsType) {
// Return the job type even if paramsType is empty
if (jobName) {
return { jobName, paramsType };
}
return null;
Expand Down
2 changes: 1 addition & 1 deletion packages/tinyjobs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ const tinyJobs = new TinyJobs<TinyJobsTypes>();
This will provide type safety for the parameters passed to the job during invocation.

## Roadmap
TinyJobs is not feature complete and still in early stages, you can refer to the roadmap for the list of currently planend features and their progress [here](https://github.com/orgs/Climactic/projects/1/views/1).
TinyJobs is not feature complete and still in early stages, you can refer to the roadmap for the list of currently planend features and their progress [here](https://github.com/orgs/Climactic/projects/1/views/4).

## License
TinyJobs is licensed under the [Apache-2.0](LICENSE).
11 changes: 10 additions & 1 deletion packages/tinyjobs/src/lib/TinyJobsEventsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { EventEmitter } from "events";
import IORedis from "ioredis";

import { TinyJobEvents } from "../types";
import type { JobCompletedData, JobFailedData } from "./types/eventsData";
import type {
JobCancelledData,
JobCompletedData,
JobFailedData,
} from "./types/eventsData";
import { getJobNameRedisKey } from "../utils/utils";

type TinyJobEventsConstructorTypes = {
Expand Down Expand Up @@ -73,6 +77,7 @@ class TinyJobEventsHandler extends EventEmitter {
// Override the emit method with proper typing
emit(event: TinyJobEvents.JOB_COMPLETE, job: JobCompletedData): boolean;
emit(event: TinyJobEvents.JOB_FAILED, job: JobFailedData): boolean;
emit(event: TinyJobEvents.JOB_CANCELLED, job: JobCancelledData): boolean;
emit(event: string | symbol, ...args: any[]): boolean {
return super.emit(event, ...args);
}
Expand All @@ -86,6 +91,10 @@ class TinyJobEventsHandler extends EventEmitter {
event: TinyJobEvents.JOB_FAILED,
listener: (job: JobFailedData) => void
): this;
on(
event: TinyJobEvents.JOB_CANCELLED,
listener: (job: JobCancelledData) => void
): this;
on(event: string | symbol, listener: (...args: any[]) => void): this {
return super.on(event, listener);
}
Expand Down
16 changes: 15 additions & 1 deletion packages/tinyjobs/src/lib/TinyJobsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { generateRandomUid, getJobNameRedisKey } from "../utils/utils";
import { getConfig } from "../utils/config";
import { loadJobsFromDir } from "../utils/jobs";
import { TinyJobEvents } from "../types";
import { string } from "valibot";

/**
* TinyJobsConstructorTypes
Expand Down Expand Up @@ -299,7 +300,20 @@ class TinyJobs<T> {
jobName as string
);

return queuedJob.id;
return queuedJob.id as string;
}

public async cancel<K extends keyof T>(jobName: K, jobId: string) {
const job = await this.queue.getJob(jobId);
if (!job) throw new Error(`Job with id ${jobId} not found.`);

await job.remove().then(async () => {
await this.redis.hdel(getJobNameRedisKey(jobName as string), jobId);
this.events.emit(TinyJobEvents.JOB_CANCELLED, {
jobId,
jobName: jobName as string,
});
});
}
}

Expand Down
5 changes: 5 additions & 0 deletions packages/tinyjobs/src/lib/types/eventsData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ export type JobFailedData = {
jobName: string;
failedReason: string;
};

export type JobCancelledData = {
jobId: string;
jobName: string;
};
1 change: 1 addition & 0 deletions packages/tinyjobs/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export enum TinyJobEvents {
"JOB_COMPLETE" = "JOB_COMPLETE",
"JOB_FAILED" = "JOB_FAILED",
"JOB_CANCELLED" = "JOB_CANCELLED",
}

0 comments on commit f21cfb4

Please sign in to comment.