Добавлена обработка ошибок в парсер календарных событий

This commit is contained in:
Gnedov Pavel 2023-08-23 04:02:29 +07:00
parent 61371282b1
commit 4d693156d3
2 changed files with 36 additions and 10 deletions

View file

@ -1,6 +1,6 @@
import { IssueEnhancerInterface } from '@app/event-emitter/issue-enhancers/issue-enhancer-interface'; import { IssueEnhancerInterface } from '@app/event-emitter/issue-enhancers/issue-enhancer-interface';
import { RedmineTypes } from '@app/event-emitter/models/redmine-types'; import { RedmineTypes } from '@app/event-emitter/models/redmine-types';
import { Injectable } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import * as Luxon from 'luxon'; import * as Luxon from 'luxon';
import { CalendarEvent } from '../models/calendar-event'; import { CalendarEvent } from '../models/calendar-event';
import * as DatesParser from '../utils/string-with-dates-parser'; import * as DatesParser from '../utils/string-with-dates-parser';
@ -23,6 +23,8 @@ export const UNKNOWN_CALENDAR_EVENT = 'Unknown calendar event';
@Injectable() @Injectable()
export class CalendarEnhancer implements IssueEnhancerInterface { export class CalendarEnhancer implements IssueEnhancerInterface {
private logger = new Logger(CalendarEnhancer.name);
name = 'calendar'; name = 'calendar';
constructor( constructor(
@ -30,16 +32,27 @@ export class CalendarEnhancer implements IssueEnhancerInterface {
public customFields: CustomFieldParserParams[], public customFields: CustomFieldParserParams[],
public descriptionCalendarParams: DescriptionParserParams, public descriptionCalendarParams: DescriptionParserParams,
public calendarEventsKey: string, public calendarEventsKey: string,
) {} ) {
const initParams = {useForProjects, customFields, descriptionCalendarParams, calendarEventsKey};
this.logger.debug(`Calendar enhancer init with ${JSON.stringify(initParams)}`);
}
async enhance( async enhance(
issue: RedmineTypes.ExtendedIssue, issue: RedmineTypes.ExtendedIssue,
): Promise<RedmineTypes.ExtendedIssue> { ): Promise<RedmineTypes.ExtendedIssue> {
const res: RedmineTypes.ExtendedIssue = { ...issue }; const res: RedmineTypes.ExtendedIssue = { ...issue };
if (!this.checkProject(issue)) return res; if (!this.checkProject(res)) {
return res;
}
issue[this.calendarEventsKey] = this.getCalendarEvents(issue); try {
res[this.calendarEventsKey] = this.getCalendarEvents(res);
} catch (ex) {
this.logger.error(`Error at parsing calendar events, message - ${ex}`);
return res;
}
this.logger.debug(`Calendar events for #${issue.id}: issue.${this.calendarEventsKey} = ${JSON.stringify(res[this.calendarEventsKey])}`);
return res; return res;
} }
@ -108,9 +121,9 @@ export class CalendarEnhancer implements IssueEnhancerInterface {
return { return {
from: from.toISO(), from: from.toISO(),
fromTimestamp: from.toSeconds(), fromTimestamp: from.toMillis(),
to: to.toISO(), to: to.toISO(),
toTimestamp: to.toSeconds(), toTimestamp: to.toMillis(),
fullDay: Boolean(params.fullDay), fullDay: Boolean(params.fullDay),
description: params.alias || cf.name || UNKNOWN_CALENDAR_EVENT, description: params.alias || cf.name || UNKNOWN_CALENDAR_EVENT,
}; };

View file

@ -1,6 +1,7 @@
import Moo from 'moo'; import * as Moo from 'moo';
import { CalendarEvent } from '../models/calendar-event'; import { CalendarEvent } from '../models/calendar-event';
import Luxon from 'luxon'; import * as Luxon from 'luxon';
import { Logger } from '@nestjs/common';
export const DEFAULT_PARAMS: Moo.Rules = { export const DEFAULT_PARAMS: Moo.Rules = {
WS: /[ \t]+/, WS: /[ \t]+/,
@ -13,12 +14,14 @@ export const DEFAULT_PARAMS: Moo.Rules = {
NL: { match: /\n/, lineBreaks: true }, NL: { match: /\n/, lineBreaks: true },
}; };
export const DEFAULT_DATE_FORMATS = ['dd.MM.yy', 'dd.MM.yyyy', 'yyyy-MM-dd']; export const DEFAULT_DATE_FORMATS = ['yyyy-MM-dd', 'dd.MM.yyyy', 'dd.MM.yy'];
export const DEFAULT_TIME_FORMATS = ['HH:mm', 'HH:mm:ss']; export const DEFAULT_TIME_FORMATS = ['HH:mm:ss', 'HH:mm'];
export const DEFAULT_EVENT_DURATION = 60 * 60 * 1000; // 1 hour in millis export const DEFAULT_EVENT_DURATION = 60 * 60 * 1000; // 1 hour in millis
const logger = new Logger('string-with-dates-parser');
export function parse(str: string, params?: Moo.Rules): Moo.Token[] { export function parse(str: string, params?: Moo.Rules): Moo.Token[] {
if (!params) params = DEFAULT_PARAMS; if (!params) params = DEFAULT_PARAMS;
try { try {
@ -32,6 +35,7 @@ export function parse(str: string, params?: Moo.Rules): Moo.Token[] {
} }
return res; return res;
} catch (ex) { } catch (ex) {
logger.error(`Error at parse str=${str} with params=${params}, error message - ${ex}`);
return []; return [];
} }
} }
@ -42,10 +46,17 @@ export type ParserOpts = {
timeFormats?: string[]; timeFormats?: string[];
}; };
export const DEFAULT_PARSER_OPTS: ParserOpts = {
rules: DEFAULT_PARAMS,
dateFormats: DEFAULT_DATE_FORMATS,
timeFormats: DEFAULT_TIME_FORMATS,
};
export function parseDate( export function parseDate(
str: string, str: string,
formats?: string[], formats?: string[],
): Luxon.DateTime | null { ): Luxon.DateTime | null {
if (!str) return null;
if (!formats) formats = DEFAULT_DATE_FORMATS; if (!formats) formats = DEFAULT_DATE_FORMATS;
let res: Luxon.DateTime; let res: Luxon.DateTime;
for (let i = 0; i < formats.length; i++) { for (let i = 0; i < formats.length; i++) {
@ -60,6 +71,7 @@ export function parseTime(
str: string, str: string,
formats?: string[], formats?: string[],
): Luxon.Duration | null { ): Luxon.Duration | null {
if (!str) return null;
if (!formats) formats = DEFAULT_TIME_FORMATS; if (!formats) formats = DEFAULT_TIME_FORMATS;
let res: Luxon.DateTime; let res: Luxon.DateTime;
for (let i = 0; i < formats.length; i++) { for (let i = 0; i < formats.length; i++) {
@ -82,6 +94,7 @@ export function parseToCalendarEvent(
str: string, str: string,
opts?: ParserOpts, opts?: ParserOpts,
): CalendarEvent | null { ): CalendarEvent | null {
if (!opts) opts = DEFAULT_PARSER_OPTS;
const tokens = parse(str, opts?.rules); const tokens = parse(str, opts?.rules);
const words = tokens.filter((i) => i.type === 'word'); const words = tokens.filter((i) => i.type === 'word');