-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
feat(api,worker): timed digest logic #3359
feat(api,worker): timed digest logic #3359
Conversation
82be2a5
to
089581c
Compare
@@ -27,6 +28,7 @@ export const USE_CASES = [ | |||
DigestFilterSteps, | |||
DigestFilterStepsRegular, | |||
DigestFilterStepsBackoff, | |||
DigestFilterStepsTimed, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the new use-case to filter steps for the timed digest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
both worker/api are using it... the api app uses it because of the batch endpoint... the worker app has the logic to handle the trigger events from the queue and parse to the jobs
@ApiPropertyOptional({ enum: [...Object.values(OrdinalEnum)] }) | ||
ordinal?: OrdinalEnum; | ||
|
||
@ApiPropertyOptional() | ||
ordinalValue?: string; | ||
@ApiPropertyOptional({ enum: [...Object.values(OrdinalValueEnum)] }) | ||
ordinalValue?: OrdinalValueEnum; | ||
|
||
@ApiPropertyOptional() | ||
monthlyType?: string; | ||
@ApiPropertyOptional({ enum: [...Object.values(MonthlyTypeEnum)] }) | ||
monthlyType?: MonthlyTypeEnum; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated swagger enums and values
<Radio.Group spacing={0} defaultValue="each" value={radioGroup.value} onChange={radioGroup.onChange}> | ||
<Radio.Group | ||
spacing={0} | ||
defaultValue={MonthlyTypeEnum.EACH} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use enums instead of strings
const atTime = watch(`steps.${index}.metadata.timed.atTime`); | ||
const weekDays = watch(`steps.${index}.metadata.timed.weekDays`) || []; | ||
const monthDays = watch(`steps.${index}.metadata.timed.monthDays`) || []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated names for these fields that were missed in previous PR
timed: { | ||
atTime: { | ||
type: Schema.Types.String, | ||
}, | ||
weekDays: [Schema.Types.String], | ||
monthDays: [Schema.Types.Number], | ||
ordinal: { | ||
type: Schema.Types.String, | ||
}, | ||
ordinalValue: { | ||
type: Schema.Types.String, | ||
}, | ||
monthlyType: { | ||
type: Schema.Types.String, | ||
}, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated job schema
if (IS_ENTERPRISE && stepMetadata.type === DigestTypeEnum.TIMED) { | ||
const timedDigestMeta = stepMetadata as IDigestTimedMetadata; | ||
|
||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const { TimedDigestDelayService } = require('@novu/digest-schedule'); | ||
|
||
return TimedDigestDelayService.calculate({ | ||
unit: timedDigestMeta.unit, | ||
amount: timedDigestMeta.amount, | ||
atTime: timedDigestMeta.timed?.atTime, | ||
weekDays: timedDigestMeta.timed?.weekDays, | ||
monthDays: timedDigestMeta.timed?.monthDays, | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the calculations for the timed digest delay
@@ -46,32 +44,11 @@ export class AddDigestJob { | |||
): Promise<AddDigestJobResult> { | |||
const { job } = command; | |||
|
|||
this.validateDigest(job); | |||
validateDigest(job); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved to the helper functions outside
|
||
// TODO: timed digest | ||
if ( | ||
this.isRegularDigest(job.digest.type) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed this check that I've added before
@@ -0,0 +1,127 @@ | |||
import { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the validation helper functions to check the digest metadata values
import { DigestFilterSteps } from './digest-filter-steps.usecase'; | ||
|
||
@Injectable() | ||
export class DigestFilterStepsTimed { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the use-case to filter steps for the timed digest run... basically at first trigger we will create all the jobs from the template steps; on subsequent triggers if digest is running we will only create the jobs from the steps that are before the digest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this different from the regular backoff?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not much but I've improved it a little.
The regular digest filter use-case: always creates a jobs array based on template steps, even if there is a digest job delayed, and then when the digest is running it marks all other digest jobs as completed. This leads to other jobs in the pending state forever.
The timed digest filter use-case: obviously creates jobs based on the template steps, but it checks if there is a delayed timed digest job, and if there is it just creates a jobs array from the steps that are before the digest, so like it cuts the jobs array.
I've asked this question before on the Discord, but no one has answered it: https://discord.com/channels/895029566685462578/1045289346598703164/1096406448839331941
return 0; | ||
} | ||
|
||
toMilliseconds(amount: number, unit: DigestUnitEnum): number { | ||
private toMilliseconds(amount: number, unit: DigestUnitEnum): number { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we make this private?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because it's not used anywhere now only internally
apps/web/src/pages/templates/workflow/digest/ScheduleMonthlyFields.tsx
Outdated
Show resolved
Hide resolved
apps/web/src/pages/templates/workflow/digest/ScheduleMonthlyFields.tsx
Outdated
Show resolved
Hide resolved
apps/web/src/pages/templates/workflow/digest/WillBeSentHeader.tsx
Outdated
Show resolved
Hide resolved
SUNDAY = 'sunday', | ||
MONDAY = 'monday', | ||
TUESDAY = 'tuesday', | ||
WEDNESDAY = 'wednesday', | ||
THURSDAY = 'thursday', | ||
FRIDAY = 'friday', | ||
SATURDAY = 'saturday', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we plan to use this Enum values? Mostly as day names should be capitalised.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This enum is reused between FE/BE.
On the FE we do use it as values for the dropdown, but the labels are capitalized.
On the BE we do have validation for the request value to be one of the enum values, also it is used for the timed digest calculations.
packages/application-generic/src/usecases/add-job/validation.ts
Outdated
Show resolved
Hide resolved
packages/application-generic/src/usecases/add-job/validation.ts
Outdated
Show resolved
Hide resolved
…te-digesting-logic-to-support-scheduled-type-main
…pport-scheduled-type-main
What change does this PR introduce?
In this PR:
Tests will be added in a separate PR.
Link to the related enterprise package PR: https://github.com/novuhq/packages-enterprise/pull/2
Why was this change needed?
This PR is a part of the Timed Digest feature.
Other information (Screenshots)