Skip to content

Commit

Permalink
Merge pull request #72 from crazyantlabs/feature/jitter
Browse files Browse the repository at this point in the history
Feature/jitter
  • Loading branch information
motymichaely authored Jun 26, 2024
2 parents e3b7985 + eddaec1 commit 31be4be
Show file tree
Hide file tree
Showing 19 changed files with 97 additions and 29 deletions.
54 changes: 28 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ $ npm install -g heroku-cron
$ heroku COMMAND
running command...
$ heroku (--version|-v)
heroku-cron/1.1.8 darwin-x64 node-v20.8.0
heroku-cron/1.2.3 darwin-x64 node-v20.8.0
$ heroku --help [COMMAND]
USAGE
$ heroku COMMAND
Expand Down Expand Up @@ -82,7 +82,7 @@ EXAMPLES
$ heroku cron --app your-app --json
```

_See code: [src/commands/cron/index.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/index.ts)_
_See code: [src/commands/cron/index.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/index.ts)_

## `heroku cron:jobs`

Expand Down Expand Up @@ -115,7 +115,7 @@ EXAMPLES
$ heroku cron:jobs --app=your-app --csv
```

_See code: [src/commands/cron/jobs/index.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/index.ts)_
_See code: [src/commands/cron/jobs/index.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/index.ts)_

## `heroku cron:jobs:clear`

Expand All @@ -142,7 +142,7 @@ EXAMPLES
$ heroku cron:jobs:clear --app your-app --confirm your-app
```

_See code: [src/commands/cron/jobs/clear.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/clear.ts)_
_See code: [src/commands/cron/jobs/clear.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/clear.ts)_

## `heroku cron:jobs:create`

Expand All @@ -151,18 +151,19 @@ create a job on Cron To Go
```
USAGE
$ heroku cron:jobs:create -a <value> [-r <value>] [--json] [--nickname <value>] [--schedule <value>] [--timezone
<value>] [--command <value>] [--dyno
Eco|Basic|Standard-1X|Standard-2X|Performance-M|Performance-L|Private-S|Private-M|Private-L] [--timeout <value>]
[--state enabled|paused] [--retries <value>]
<value>] [--command <value>] [--dyno Eco|Basic|Standard-1X|Standard-2X|Performance-M|Performance-L|Performance-L-RAM
|Performance-XL|Performance-2XL|Private-S|Private-M|Private-L|Private-L-RAM|Private-XL|Private-2XL] [--timeout
<value>] [--state enabled|paused] [--retries <value>] [--jitter <value>]
FLAGS
-a, --app=<value> (required) app to run command against
-r, --remote=<value> git remote of app to use
--command=<value> command to run as a one-off dyno either as the command to execute, or a process type that is
present in your apps's Procfile
--dyno=<option> size of the one-off dyno
<options:
Eco|Basic|Standard-1X|Standard-2X|Performance-M|Performance-L|Private-S|Private-M|Private-L>
<options: Eco|Basic|Standard-1X|Standard-2X|Performance-M|Performance-L|Performance-L-RAM|Perfor
mance-XL|Performance-2XL|Private-S|Private-M|Private-L|Private-L-RAM|Private-XL|Private-2XL>
--jitter=<value> the amount of jitter to add to the schedule, in minutes
--json return the results as JSON
--nickname=<value> nickname of the job. Leave blank to use the job command
--retries=<value> number of attempts to make to run a job using the exponential back-off procedure
Expand All @@ -183,7 +184,7 @@ EXAMPLES
$ heroku cron:jobs:create --app your-app
```

_See code: [src/commands/cron/jobs/create.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/create.ts)_
_See code: [src/commands/cron/jobs/create.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/create.ts)_

## `heroku cron:jobs:delete JOB`

Expand Down Expand Up @@ -213,7 +214,7 @@ EXAMPLES
$ heroku cron:jobs:delete 01234567-89ab-cdef-0123-456789abcdef --app your-app --confirm 01234567-89ab-cdef-0123-456789abcdef
```

_See code: [src/commands/cron/jobs/delete.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/delete.ts)_
_See code: [src/commands/cron/jobs/delete.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/delete.ts)_

## `heroku cron:jobs:export FILENAME`

Expand Down Expand Up @@ -242,7 +243,7 @@ EXAMPLES
$ heroku cron:jobs:export /tmp/manifest.yml --app your-app
```

_See code: [src/commands/cron/jobs/export.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/export.ts)_
_See code: [src/commands/cron/jobs/export.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/export.ts)_

## `heroku cron:jobs:import FILENAME`

Expand Down Expand Up @@ -277,7 +278,7 @@ EXAMPLES
$ heroku cron:jobs:import manifest.yml --app your-app --delete --confirm your-app
```

_See code: [src/commands/cron/jobs/import.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/import.ts)_
_See code: [src/commands/cron/jobs/import.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/import.ts)_

## `heroku cron:jobs:info JOB`

Expand Down Expand Up @@ -305,7 +306,7 @@ EXAMPLES
$ heroku cron:jobs:info 01234567-89ab-cdef-0123-456789abcdef --app your-app --json
```

_See code: [src/commands/cron/jobs/info.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/info.ts)_
_See code: [src/commands/cron/jobs/info.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/info.ts)_

## `heroku cron:jobs:logs JOB`

Expand Down Expand Up @@ -338,7 +339,7 @@ EXAMPLES
$ heroku cron:jobs:logs 01234567-89ab-cdef-0123-456789abcdef --app your-app --tail
```

_See code: [src/commands/cron/jobs/logs.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/logs.ts)_
_See code: [src/commands/cron/jobs/logs.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/logs.ts)_

## `heroku cron:jobs:pause JOB`

Expand All @@ -365,7 +366,7 @@ EXAMPLES
$ heroku cron:jobs:pause 01234567-89ab-cdef-0123-456789abcdef --app your-app
```

_See code: [src/commands/cron/jobs/pause.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/pause.ts)_
_See code: [src/commands/cron/jobs/pause.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/pause.ts)_

## `heroku cron:jobs:resume JOB`

Expand All @@ -392,7 +393,7 @@ EXAMPLES
$ heroku cron:jobs:resume 01234567-89ab-cdef-0123-456789abcdef --app your-app
```

_See code: [src/commands/cron/jobs/resume.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/resume.ts)_
_See code: [src/commands/cron/jobs/resume.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/resume.ts)_

## `heroku cron:jobs:run JOB`

Expand Down Expand Up @@ -431,7 +432,7 @@ EXAMPLES
$ heroku cron:jobs:run 01234567-89ab-cdef-0123-456789abcdef --app your-app --tail --confirm 01234567-89ab-cdef-0123-456789abcdef
```

_See code: [src/commands/cron/jobs/run.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/run.ts)_
_See code: [src/commands/cron/jobs/run.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/run.ts)_

## `heroku cron:jobs:trigger JOB`

Expand Down Expand Up @@ -477,9 +478,9 @@ update a job on Cron To Go
```
USAGE
$ heroku cron:jobs:update [JOB] -a <value> [-r <value>] [--json] [--nickname <value>] [--schedule <value>]
[--timezone <value>] [--command <value>] [--dyno
Eco|Basic|Standard-1X|Standard-2X|Performance-M|Performance-L|Private-S|Private-M|Private-L] [--timeout <value>]
[--state enabled|paused] [--retries <value>]
[--timezone <value>] [--command <value>] [--dyno Eco|Basic|Standard-1X|Standard-2X|Performance-M|Performance-L|Perfo
rmance-L-RAM|Performance-XL|Performance-2XL|Private-S|Private-M|Private-L|Private-L-RAM|Private-XL|Private-2XL]
[--timeout <value>] [--state enabled|paused] [--retries <value>] [--jitter <value>]
ARGUMENTS
JOB unique ID of the job
Expand All @@ -490,8 +491,9 @@ FLAGS
--command=<value> command to run as a one-off dyno either as the command to execute, or a process type that is
present in your apps's Procfile
--dyno=<option> size of the one-off dyno
<options:
Eco|Basic|Standard-1X|Standard-2X|Performance-M|Performance-L|Private-S|Private-M|Private-L>
<options: Eco|Basic|Standard-1X|Standard-2X|Performance-M|Performance-L|Performance-L-RAM|Perfor
mance-XL|Performance-2XL|Private-S|Private-M|Private-L|Private-L-RAM|Private-XL|Private-2XL>
--jitter=<value> the amount of jitter to add to the schedule, in minutes
--json return the results as JSON
--nickname=<value> nickname of the job. Leave blank to use the job command
--retries=<value> number of attempts to make to run a job using the exponential back-off procedure
Expand All @@ -507,10 +509,10 @@ DESCRIPTION
Read more about this feature at https://devcenter.heroku.com/articles/crontogo
EXAMPLES
$ heroku cron:jobs:create -a your-app
$ heroku cron:jobs:update -a your-app
$ heroku cron:jobs:create --app your-app
$ heroku cron:jobs:update --app your-app
```

_See code: [src/commands/cron/jobs/update.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.1.8/src/commands/cron/jobs/update.ts)_
_See code: [src/commands/cron/jobs/update.ts](https://github.com/crazyantlabs/heroku-cli-plugin-cron/blob/v1.2.3/src/commands/cron/jobs/update.ts)_
<!-- commandsstop -->
1 change: 1 addition & 0 deletions examples/manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
dyno: 'Basic'
timeout: 300
state: 'enabled'
jitter: 5

- nickname: Every month (on the 1st at 09:00)
timezone: 'UTC'
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "heroku-cron",
"version": "1.1.8",
"version": "1.2.3",
"description": "Heroku CLI plugin for Cron To Go",
"author": "Moty Michaely @motymichaely",
"bin": {
Expand Down
13 changes: 13 additions & 0 deletions src/commands/cron/jobs/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ export default class JobsCreate extends BaseCommand {
description: 'number of attempts to make to run a job using the exponential back-off procedure',
required: false,
}),
jitter: flags.integer({
description: 'the amount of jitter to add to the schedule, in minutes',
required: false,
}),
}

static args = []
Expand Down Expand Up @@ -136,6 +140,14 @@ export default class JobsCreate extends BaseCommand {
validate(input) {
return validateAnswer('Retries', input)
},
}, {
type: 'number',
name: 'jitter',
message: 'What is the jitter (in minutes)?',
default: 0,
validate(input) {
return validateAnswer('Jitter', input)
},
}, {
type: 'list',
name: 'state',
Expand Down Expand Up @@ -165,6 +177,7 @@ export default class JobsCreate extends BaseCommand {
},
Retries: answers.retries,
State: answers.state,
Jitter: answers.jitter
}

// Validate jobCreatePayload
Expand Down
1 change: 1 addition & 0 deletions src/commands/cron/jobs/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export default class JobsExport extends BaseCommand {
command: _.get(job, 'Target.Command'),
timeout: _.get(job, 'Target.TimeToLive'),
retries: _.get(job, 'Retries'),
jitter: _.get(job, 'Jitter'),
state: _.get(job, 'State'),
}
}),
Expand Down
1 change: 1 addition & 0 deletions src/commands/cron/jobs/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ export default class JobsImport extends BaseCommand {
if (_.has(job, 'command')) _.set(jobCreatePayload, 'Target.Command', job.command)
if (_.has(job, 'timeout')) _.set(jobCreatePayload, 'Target.TimeToLive', job.timeout)
if (_.has(job, 'retries')) _.set(jobCreatePayload, 'Retries', job.retries)
if (_.has(job, 'jitter')) _.set(jobCreatePayload, 'Jitter', job.jitter)
if (_.has(job, 'state')) _.set(jobCreatePayload, 'State', job.state)

// Validate jobCreatePayload
Expand Down
3 changes: 3 additions & 0 deletions src/commands/cron/jobs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ export default class JobsList extends BaseCommand {
Retries: {header: 'Retries', extended: true, get: (job:Job) => {
return job.Retries || '-'
}},
Jitter: {header: 'Jitter', extended: true, get: (job:Job) => {
return job.Jitter || '-'
}},
CreatedAt: {header: 'Created', extended: true, get: (job:Job) => {
return formatDate(job.CreatedAt)
}},
Expand Down
1 change: 1 addition & 0 deletions src/commands/cron/jobs/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export default class JobsInfo extends BaseCommand {
Schedule: res.ScheduleExpression,
Timezone: res.Timezone,
Retries: res.Retries,
Jitter: res.Jitter,
Created: formatDate(res.CreatedAt),
Updated: formatDate(res.UpdatedAt),
})
Expand Down
5 changes: 3 additions & 2 deletions src/commands/cron/jobs/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export default class JobsUpdate extends BaseCommand {
static description = 'update a job on Cron To Go\nRead more about this feature at https://devcenter.heroku.com/articles/crontogo'

static examples = [
'$ heroku cron:jobs:create -a your-app',
'$ heroku cron:jobs:create --app your-app',
'$ heroku cron:jobs:update -a your-app',
'$ heroku cron:jobs:update --app your-app',
]

static flags = {
Expand Down Expand Up @@ -52,6 +52,7 @@ export default class JobsUpdate extends BaseCommand {
if (_.has(flags, 'timeout')) _.set(jobUpdatePayload, 'Target.TimeToLive', flags.timeout)
if (_.has(flags, 'state')) _.set(jobUpdatePayload, 'State', flags.state)
if (_.has(flags, 'retries')) _.set(jobUpdatePayload, 'Retries', flags.retries)
if (_.has(flags, 'jitter')) _.set(jobUpdatePayload, 'Jitter', flags.jitter)

// Validate jobUpdatePayload
const validation = ValidationService.getJobValidationService().validate(jobUpdatePayload)
Expand Down
8 changes: 8 additions & 0 deletions src/lib/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,15 @@ export enum DynoSize {
STANDARD_2X = 'Standard-2X',
PERFORMANCE_M = 'Performance-M',
PERFORMANCE_L = 'Performance-L',
PERFORMANCE_L_RAM = 'Performance-L-RAM',
PERFORMANCE_XL = 'Performance-XL',
PERFORMANCE_2XL = 'Performance-2XL',
PRIVATE_S = 'Private-S',
PRIVATE_M = 'Private-M',
PRIVATE_L = 'Private-L',
PRIVATE_L_RAM = 'Private-L-RAM',
PRIVATE_XL = 'Private-XL',
PRIVATE_2XL = 'Private-2XL',
}

export interface JobTarget {
Expand All @@ -64,6 +70,7 @@ export interface Job {
CreatedAt: number;
},
Retries: number;
Jitter: number;
CreatedAt: number;
UpdatedAt: number;
[k: string]: any;
Expand Down Expand Up @@ -120,6 +127,7 @@ export interface ManifestJob {
command: string;
timeout: number;
retries: number;
jitter: number;
state: string;
[k: string]: any;
}
16 changes: 16 additions & 0 deletions src/lib/validation-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,22 @@ class ValidationService {
min: 0, allow_leading_zeroes: false,
}],
message: "Unfortunately, retries can't be lower than 0.",
}, {
field: 'Jitter',
method: 'isInt',
validWhen: true,
args: [{
max: 1440, allow_leading_zeroes: false,
}],
message: "Unfortunately, jitter can't be greater than 1440.",
}, {
field: 'Jitter',
method: 'isInt',
validWhen: true,
args: [{
min: 0, allow_leading_zeroes: false,
}],
message: "Unfortunately, jitter can't be lower than 0.",
},
])
}
Expand Down
12 changes: 12 additions & 0 deletions test/commands/cron/jobs/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const jobStub = {
CreatedAt: '2020-01-01T12:00:00Z',
},
Retries: 3,
Jitter: 0,
CreatedAt: '2020-01-01T12:00:00Z',
UpdatedAt: '2020-01-01T12:00:00Z',
}
Expand All @@ -40,6 +41,7 @@ const createCommandJobStub = _.merge({}, jobStub, {Target: {Command: 'created-co
const createDynoJobStub = _.merge({}, jobStub, {Target: {Size: 'Standard-1X'}})
const createTimeoutJobStub = _.merge({}, jobStub, {Target: {TimeToLive: 700}})
const createRetriesJobStub = _.merge({}, jobStub, {Retries: 5})
const createJitterJobStub = _.merge({}, jobStub, {Jitter: 5})
const createStateJobStub = _.merge({}, jobStub, {State: 'paused'})
const multiUpdateJobStub = _.merge({}, jobStub, {Alias: 'multi-creates', State: 'paused'})
const createRateJobStub = _.merge({}, jobStub, {ScheduleExpression: '3 hours'})
Expand Down Expand Up @@ -153,6 +155,14 @@ describe('cron:jobs:create', () => {
expect(ctx.stdout).to.contain('"Retries": 5')
})

testFactory(createJitterJobStub)
.stdout()
.command(['cron:jobs:create', '--app', app, '--jitter', '5', '--json'])
.it('shows detailed information about newly created Cron To Go job with jitter in JSON format', ctx => {
expect(ctx.stdout).to.contain('"Alias": "my-job"')
expect(ctx.stdout).to.contain('"Jitter": 5')
})

testFactory(multiUpdateJobStub)
.stdout()
.command(['cron:jobs:create', '--app', app, '--nickname', multiUpdateJobStub.Alias, '--state', multiUpdateJobStub.State, '--json'])
Expand Down Expand Up @@ -183,6 +193,7 @@ describe('cron:jobs:create', () => {
command: jobStub.Target?.Command,
timeout: jobStub.Target?.TimeToLive,
retries: jobStub.Retries,
jitter: jobStub.Jitter,
state: jobStub.State,
})
})
Expand Down Expand Up @@ -211,6 +222,7 @@ describe('cron:jobs:create', () => {
command: jobStub.Target?.Command,
timeout: jobStub.Target?.TimeToLive,
retries: jobStub.Retries,
jitter: jobStub.Jitter,
state: jobStub.State,
})
})
Expand Down
1 change: 1 addition & 0 deletions test/commands/cron/jobs/export.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const jobsListStub = [{
State: 'running',
CreatedAt: '2020-01-01T12:00:00Z',
},
Jitter: 5,
CreatedAt: '2020-01-01T12:00:00Z',
UpdatedAt: '2020-01-01T12:00:00Z',
}, {
Expand Down
Loading

0 comments on commit 31be4be

Please sign in to comment.