ah-resque-ui
Version:
A resque administration website for actionhero
323 lines (286 loc) • 10.3 kB
text/typescript
import {
ResqueDelayedJobs,
ResqueDelLock,
ResqueDelQueue,
ResqueFailedCount,
ResqueLoadWorkerQueues,
ResqueLocks,
ResqueQueued,
ResqueRedisInfo,
ResqueResqueDetails,
ResqueResqueFailed,
} from "../src/actions/ah-resque-ui";
import { Process, task, api, specHelper } from "actionhero";
const sleep = (zzz = 100) => {
return new Promise((resolve) => {
setTimeout(resolve, zzz);
});
};
const app = new Process();
describe("ah-resque-ui", () => {
beforeAll(async () => {
// jest.setTimeout(10000);
await app.initialize();
await api.redis.clients.client.flushdb();
await app.start();
// @ts-ignore
api.tasks.tasks.testTask = {
name: "testTask",
description: "testTask",
queue: "testQueue",
frequency: 0,
run: async (params) => {
if (params.fail === true) {
throw new Error("broken");
}
},
};
// api.resque.multiWorker.start();
api.tasks.jobs.testTask = api.tasks.jobWrapper("testTask");
await sleep(100); // for the workers to start
});
afterAll(async () => {
// await api.resque.multiWorker.stop();
delete api.tasks.tasks.testTask;
delete api.tasks.jobs.testTask;
await app.stop();
});
it("resque:redisInfo", async () => {
const response = await specHelper.runAction<ResqueRedisInfo>(
"resque:redisInfo"
);
const info = response.redisInfo.join("\n");
expect(info).toMatch(/redis_version/);
expect(info).toMatch(/used_memory/);
expect(info).toMatch(/used_memory_human/);
});
it("resque:forceCleanWorker", () => {}); // TODO
describe("with locks", () => {
beforeEach(async () => {
await api.resque.queue.connection.redis.set(
api.resque.queue.connection.key("lock:lists:queueName:jobName:[{}]"),
123
);
});
beforeEach(async () => {
await api.resque.queue.connection.redis.set(
api.resque.queue.connection.key(
"workerslock:lists:queueName:jobName:[{}]"
),
456
);
});
afterEach(async () => {
await api.resque.queue.connection.redis.del(
api.resque.queue.connection.key("lock:lists:queueName:jobName:[{}]")
);
});
afterEach(async () => {
await api.resque.queue.connection.redis.del(
api.resque.queue.connection.key(
"workerslock:lists:queueName:jobName:[{}]"
)
);
});
it("resque:locks", async () => {
const response = await specHelper.runAction<ResqueLocks>("resque:locks");
expect(Object.keys(response.locks).length).toEqual(2);
expect(response.locks["lock:lists:queueName:jobName:[{}]"]).toEqual(
"123"
);
expect(
response.locks["workerslock:lists:queueName:jobName:[{}]"]
).toEqual("456");
});
it("resque:delLock", async () => {
let response = await specHelper.runAction<ResqueDelLock>(
"resque:delLock",
{
lock: "workerslock:lists:queueName:jobName:[{}]",
}
);
expect(response.count).toEqual(1);
let locksResponse = await specHelper.runAction<ResqueLocks>(
"resque:locks"
);
expect(Object.keys(locksResponse.locks).length).toEqual(1);
expect(locksResponse.locks["lock:lists:queueName:jobName:[{}]"]).toEqual(
"123"
);
});
});
describe("with jobs", () => {
beforeEach(async () => {
await specHelper.runAction("resque:delQueue", { queue: "testQueue" });
await task.enqueue("testTask", { a: 1 }, "testQueue");
await task.enqueue("testTask", { b: 2 }, "testQueue");
await task.enqueue("testTask", { c: 3 }, "testQueue");
});
it("resque:resqueDetails", async () => {
const response = await specHelper.runAction<ResqueResqueDetails>(
"resque:resqueDetails"
);
expect(response.resqueDetails.queues.testQueue.length).toEqual(3);
expect(Object.keys(response.resqueDetails.workers).length).toEqual(1);
});
it("resque:loadWorkerQueues", async () => {
const response = await specHelper.runAction<ResqueLoadWorkerQueues>(
"resque:loadWorkerQueues"
);
const workerNames = Object.keys(response.workerQueues);
expect(workerNames.length).toBe(1);
expect(response.workerQueues[workerNames[0]]).toContain("*");
});
it("resque:queued (good)", async () => {
const response = await specHelper.runAction<ResqueQueued>(
"resque:queued",
{
queue: "testQueue",
}
);
expect(response.jobs.length).toBe(3);
});
it("resque:queued (bad)", async () => {
const response = await specHelper.runAction<ResqueQueued>(
"resque:queued",
{
queue: "xxx",
}
);
expect(response.jobs.length).toBe(0);
});
it("resque:delQueue", async () => {
await specHelper.runAction<ResqueDelQueue>("resque:delQueue", {
queue: "testQueue",
});
const response = await specHelper.runAction<ResqueQueued>(
"resque:queued",
{
queue: "testQueue",
}
);
expect(response.jobs.length).toBe(0);
});
});
describe("with delayed jobs", () => {
beforeAll(async () => {
await task.enqueueAt(1000, "testTask", { a: 1 }, "testQueue");
await task.enqueueAt(2000, "testTask", { b: 2 }, "testQueue");
await task.enqueueAt(3000, "testTask", { c: 3 }, "testQueue");
});
it("resque:delayedjobs (defaults)", async () => {
const response = await specHelper.runAction<ResqueDelayedJobs>(
"resque:delayedjobs"
);
expect(response.timestampsCount).toBe(3);
expect(Object.keys(response.delayedjobs).length).toBe(3);
expect(response.delayedjobs["1000"].tasks[0].args[0].a).toBe(1);
expect(response.delayedjobs["2000"].tasks[0].args[0].b).toBe(2);
expect(response.delayedjobs["3000"].tasks[0].args[0].c).toBe(3);
});
it("resque:delayedjobs (pagination)", async () => {
let response;
response = await specHelper.runAction("resque:delayedjobs", {
start: 0,
stop: 1,
});
expect(response.timestampsCount).toBe(3);
expect(Object.keys(response.delayedjobs).length).toBe(2);
expect(response.delayedjobs["1000"].tasks[0].args[0].a).toBe(1);
expect(response.delayedjobs["2000"].tasks[0].args[0].b).toBe(2);
response = await specHelper.runAction("resque:delayedjobs", {
start: 2,
stop: 999,
});
expect(response.timestampsCount).toBe(3);
expect(Object.keys(response.delayedjobs).length).toBe(1);
expect(response.delayedjobs["3000"].tasks[0].args[0].c).toBe(3);
});
it("resque:delDelayed", () => {}); //TODO
it("resque:runDelayed", () => {}); //TODO
});
describe("with failed jobs", () => {
beforeEach(async () => {
await specHelper.runAction("resque:delQueue", { queue: "testQueue" });
await specHelper.runAction("resque:removeAllFailed");
await task.enqueue("testTask", { a: 1, fail: true }, "testQueue");
await task.enqueue("testTask", { b: 2, fail: true }, "testQueue");
await task.enqueue("testTask", { c: 3, fail: true }, "testQueue");
// should allow time to work the bad jobs
await sleep(1000);
});
it("resque:resqueFailedCount", async () => {
const response = await specHelper.runAction<ResqueFailedCount>(
"resque:resqueFailedCount"
);
expect(response.failedCount).toBe(3);
});
it("resque:resqueFailed (defaults)", async () => {
const response = await specHelper.runAction<ResqueResqueFailed>(
"resque:resqueFailed"
);
expect(response.failed.length).toBe(3);
response.failed.forEach((j: any) => {
expect(j.queue).toBe("testQueue");
expect(j.error).toMatch("broken");
expect(j.payload.args[0].fail).toBe(true);
});
});
it("resque:resqueFailed (pagination)", async () => {
let response;
response = await specHelper.runAction("resque:resqueFailed", {
start: 0,
stop: 1,
});
expect(response.failed.length).toBe(2);
expect(response.failed[0].payload.args[0].a).toBe(1);
expect(response.failed[1].payload.args[0].b).toBe(2);
response = await specHelper.runAction("resque:resqueFailed", {
start: 2,
stop: 99,
});
expect(response.failed.length).toBe(1);
expect(response.failed[0].payload.args[0].c).toBe(3);
});
it("resque:removeFailed", async () => {
await specHelper.runAction("resque:removeFailed", { id: 1 });
const response = await specHelper.runAction<ResqueResqueFailed>(
"resque:resqueFailed"
);
expect(response.failed.length).toBe(2);
expect((response.failed[0] as any).payload.args[0].a).toBe(1);
expect((response.failed[1] as any).payload.args[0].c).toBe(3);
});
it("resque:removeAllFailed", async () => {
await specHelper.runAction("resque:removeAllFailed");
const response = await specHelper.runAction<ResqueResqueFailed>(
"resque:resqueFailed"
);
expect(response.failed.length).toBe(0);
});
it("resque:retryAndRemoveFailed", async () => {
await specHelper.runAction("resque:retryAndRemoveFailed", { id: 1 });
const response = await specHelper.runAction<ResqueResqueFailed>(
"resque:resqueFailed"
);
expect(response.failed.length).toBe(2);
expect((response.failed[0] as any).payload.args[0].a).toBe(1);
expect((response.failed[1] as any).payload.args[0].c).toBe(3);
const details = await specHelper.runAction<ResqueResqueDetails>(
"resque:resqueDetails"
);
expect(details.resqueDetails.queues.testQueue.length).toBe(1);
});
it("resque:retryAndRemoveAllFailed", async () => {
await specHelper.runAction("resque:retryAndRemoveAllFailed");
const response = await specHelper.runAction<ResqueResqueFailed>(
"resque:resqueFailed"
);
expect(response.failed.length).toBe(0);
const details = await specHelper.runAction<ResqueResqueDetails>(
"resque:resqueDetails"
);
expect(details.resqueDetails.queues.testQueue.length).toBe(3);
});
});
});