Skip to content

Commit

Permalink
feat: add task scheduling logic
Browse files Browse the repository at this point in the history
  • Loading branch information
julian-wasmeier-titanom committed May 20, 2024
1 parent e1db042 commit a65c28e
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 40 deletions.
44 changes: 35 additions & 9 deletions backend/src/assignment-scheduler.service.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,50 @@
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { dbGetTaskGroupUsers } from './db/functions/task-group';
import {
dbGetTaskGroupUsers,
dbGetTaskGroupsToCreateForCurrentInterval,
} from './db/functions/task-group';
import { dbGetAssignmentsForTaskGroup } from './db/functions/assignment-task-group';
dbCreateTaskGroupAssignment,
dbGetAssignmentsForTaskGroup,
dbGetTaskGroupsToAssignForCurrentInterval,
} from './db/functions/assignment-task-group';
import { randomFromArray } from './utils/array';

@Injectable()
export class AssignmentSchedulerService {
@Cron(CronExpression.EVERY_5_SECONDS)
async handleCron() {
console.debug('CRON job running');
const taskGroupsToCreateAssignmentsFor =
await dbGetTaskGroupsToCreateForCurrentInterval();
await dbGetTaskGroupsToAssignForCurrentInterval();
console.debug({ taskGroupsToCreateAssignmentsFor });
for (const { taskGroupId } of taskGroupsToCreateAssignmentsFor) {
const users = await dbGetTaskGroupUsers(taskGroupId);
const assignments = await dbGetAssignmentsForTaskGroup(
const userIds = await dbGetTaskGroupUsers(taskGroupId);
if (userIds.length === 0) {
continue;
}
const lastAssignments = await dbGetAssignmentsForTaskGroup(
taskGroupId,
users.length,
userIds.length,
);
console.log({ assignments });
const firstTimeAssignmentUsers = userIds.filter(
({ userId }) =>
!lastAssignments.some((assignment) => assignment.userId === userId),
);

console.debug({ userIds });
console.debug({ firstTimeAssignmentUsers });
console.debug({ lastAssignments, taskGroupId });

let nextResponsibleUserId: number;
if (firstTimeAssignmentUsers.length === 0) {
nextResponsibleUserId =
lastAssignments[lastAssignments.length - 1].userId;
} else {
nextResponsibleUserId = randomFromArray(
firstTimeAssignmentUsers,
).userId;
}

await dbCreateTaskGroupAssignment(taskGroupId, nextResponsibleUserId);
}
}
}
37 changes: 35 additions & 2 deletions backend/src/db/functions/assignment-task-group.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { desc, eq } from 'drizzle-orm';
import { count, desc, eq, or, sql } from 'drizzle-orm';
import { db } from '..';
import { taskGroupAssignmentTable } from '../schema';
import { taskGroupAssignmentTable, taskGroupTable } from '../schema';

export async function dbGetAssignmentsForTaskGroup(
taskGroupId: number,
Expand All @@ -16,3 +16,36 @@ export async function dbGetAssignmentsForTaskGroup(
}
return await result.limit(limit);
}

export async function dbCreateTaskGroupAssignment(
taskGroupId: number,
userId: number,
) {
await db.insert(taskGroupAssignmentTable).values({ taskGroupId, userId });
}

export async function dbGetTaskGroupsToAssignForCurrentInterval() {
try {
const taskGroupIdsToCreateAssignmentsFor = await db
.select({
taskGroupId: taskGroupTable.id,
})
.from(taskGroupTable)
.leftJoin(
taskGroupAssignmentTable,
eq(taskGroupTable.id, taskGroupAssignmentTable.taskGroupId),
)
.groupBy(taskGroupTable.id)
.having(
or(
eq(count(taskGroupAssignmentTable.id), 0),
sql`MAX(${taskGroupAssignmentTable.createdAt}) < (NOW() - ${taskGroupTable.interval})`,
),
);

return taskGroupIdsToCreateAssignmentsFor;
} catch (error) {
console.error({ error });
throw error;
}
}
31 changes: 2 additions & 29 deletions backend/src/db/functions/task-group.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { eq, sql } from 'drizzle-orm';
import { eq } from 'drizzle-orm';
import { CreateTaskGroup } from 'src/task-group.controller';
import { db } from '..';
import {
taskGroupAssignmentTable,
taskGroupTable,
taskGroupUserTable,
userTable,
} from '../schema';
import { taskGroupTable, taskGroupUserTable, userTable } from '../schema';

export async function dbGetTaskGroups() {
return await db.select().from(taskGroupTable);
Expand Down Expand Up @@ -44,28 +39,6 @@ export async function dbCreateTaskGroup({
}
}

export async function dbGetTaskGroupsToCreateForCurrentInterval() {
try {
const taskGroupIdsToCreateAssignmentsFor = await db
.select({
taskGroupId: taskGroupTable.id,
})
.from(taskGroupTable)
.innerJoin(
taskGroupAssignmentTable,
eq(taskGroupTable.id, taskGroupAssignmentTable.taskGroupId),
)
.groupBy(taskGroupTable.id)
.having(
sql`MAX(${taskGroupAssignmentTable.createdAt}) < (NOW() - ${taskGroupTable.interval})`,
);
return taskGroupIdsToCreateAssignmentsFor;
} catch (error) {
console.error({ error });
throw error;
}
}

export async function dbGetTaskGroupUsers(taskGroupId: number) {
try {
const taskGroupUsers = await db
Expand Down
11 changes: 11 additions & 0 deletions backend/src/utils/array.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Returns a random value from an array of data.
*
* @param array - An array of data from which to select a random value.
* @returns A random value from the array.
*/
export function randomFromArray<TItem>(array: readonly TItem[]) {
const randomIndex = Math.floor(Math.random() * array.length);
const randomValue = array[randomIndex];
return randomValue;
}

0 comments on commit a65c28e

Please sign in to comment.