Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a scheduled task to update jira ticket status into criteria progres #3044

Merged
merged 6 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,6 @@ const userPassword = 'taskany';
prisma.appConfig.create({ data: {} }),
createSheep(),
createCronJob('goalPing', '0 0 0 1 * *'),
createCronJob('externalTaskCheck', '1/10 * * * *'),
]);
})();
41 changes: 32 additions & 9 deletions src/utils/recalculateCriteriaScore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,24 @@ type GoalCalculateScore = Goal & {
* then for all goals needs recalculate score and parents project's average score
*/

interface CriteriaScoreUpdateBaseApi {
recalcCurrentGoalScore: () => CriteriaScoreUpdateApi & CriteriaScoreUpdateBaseApi;
recalcAverageProjectScore: () => CriteriaScoreUpdateApi & CriteriaScoreUpdateBaseApi;
recalcLinkedGoalsScores: () => CriteriaScoreUpdateApi & CriteriaScoreUpdateBaseApi;
}

interface CriteriaScoreUpdateApi {
run: () => Promise<void>;
makeChain: (
...names: Array<keyof CriteriaScoreUpdateBaseApi>
) => CriteriaScoreUpdateApi & CriteriaScoreUpdateBaseApi;
}

export const recalculateCriteriaScore = (goalId: string) => {
let currentGoal: GoalCalculateScore;
let countsToUpdate: number;
let count = 0;

const getCurrentGoal = async () => {
if (!currentGoal || countsToUpdate > count++) {
currentGoal = await prisma.goal.findUniqueOrThrow({
Expand All @@ -118,7 +132,7 @@ export const recalculateCriteriaScore = (goalId: string) => {
let prismaCtx: Omit<PrismaClient, ITXClientDenyList>;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const promisesChain: (() => Promise<any>)[] = [];
const promisesChain: (() => Promise<void>)[] = [];

const updateGoalScore = ({ id, score }: { id: string; score: number | null }) => {
return prismaCtx.goal.update({
Expand All @@ -127,7 +141,16 @@ export const recalculateCriteriaScore = (goalId: string) => {
});
};

const methods = {
const run = () => {
return prisma.$transaction((ctx) => {
prismaCtx = ctx;
countsToUpdate = promisesChain.length;

return promisesChain.reduce((promise, getter) => promise.then(getter), Promise.resolve());
});
};

const methods: CriteriaScoreUpdateApi & CriteriaScoreUpdateBaseApi = {
recalcCurrentGoalScore: () => {
promisesChain.push(async () => {
const goal = await getCurrentGoal();
Expand Down Expand Up @@ -181,7 +204,7 @@ export const recalculateCriteriaScore = (goalId: string) => {
group by 1
`;

return prismaCtx.$executeRaw`
await prismaCtx.$executeRaw`
update "Project" as project
set "averageScore" = scoreByProject.score
from (${countsRequests}) as scoreByProject(projectId, score)
Expand Down Expand Up @@ -252,13 +275,13 @@ export const recalculateCriteriaScore = (goalId: string) => {

return methods;
},
async run() {
return prisma.$transaction((ctx) => {
prismaCtx = ctx;
countsToUpdate = promisesChain.length;

return promisesChain.reduce((promise, getter) => promise.then(getter), Promise.resolve());
run,
makeChain(...names) {
names.forEach((name) => {
methods[name]();
});

return methods;
},
};
return methods;
Expand Down
32 changes: 31 additions & 1 deletion src/utils/worker/create.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { prisma } from '../prisma';

import * as templates from './mail/templates';
import { log } from './utils';

export const defaultJobDelay = process.env.WORKER_JOBS_DELAY ? parseInt(process.env.WORKER_JOBS_DELAY, 10) : 1000;

Expand All @@ -14,6 +15,7 @@ export enum jobKind {
email = 'email',
cron = 'cron',
comment = 'comment',
criteriaToUpdate = 'criteriaToUpdate',
}

type Templates = typeof templates;
Expand All @@ -25,15 +27,22 @@ export interface JobDataMap {
data: any;
};
cron: {
template: 'goalPing';
template: 'goalPing' | 'externalTaskCheck';
};
comment: {
goalId: string;
activityId: string;
description: string;
};
criteriaToUpdate: {
id: string;
};
}

export const castJobData = <Kind extends jobKind>(kind: Kind, data: unknown): data is JobDataMap[Kind] => {
return data != null;
};

export type JobKind = keyof JobDataMap;

interface CreateJobProps<K extends keyof JobDataMap> {
Expand All @@ -43,10 +52,27 @@ interface CreateJobProps<K extends keyof JobDataMap> {
cron?: string;
}

export const pickScheduledLastJob = async (kind: JobKind) => {
const res = await prisma.job.findMany({
where: { kind, state: jobState.scheduled },
orderBy: [{ createdAt: 'desc' }, { updatedAt: 'desc' }],
take: 1,
skip: 0,
});

if (res.length) {
return res[0];
}

return null;
};

export function createJob<K extends keyof JobDataMap>(
kind: K,
{ data, priority, delay = defaultJobDelay, cron }: CreateJobProps<K>,
) {
log(`create new ${kind} job`, JSON.stringify(data));

return prisma.job.create({
data: {
state: jobState.scheduled,
Expand Down Expand Up @@ -86,3 +112,7 @@ export function createCommentJob(data: JobDataMap['comment'], delay?: number) {
delay,
});
}

export const createCriteriaToUpdate = (data: JobDataMap['criteriaToUpdate'], delay?: number) => {
return createJob('criteriaToUpdate', { data, delay });
};
Loading
Loading