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

Add cron job endpoints #63

Merged
merged 5 commits into from
Sep 21, 2023
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
47 changes: 17 additions & 30 deletions .redocly.lint-ignore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
# See https://redoc.ly/docs/cli/ for more information.
openapi/karman.yaml:
spec:
- >-
#/components/securitySchemes/OAuth2/flows/urn:ietf:params:oauth:grant-type:token-exchange
- '#/components/securitySchemes/OAuth2/flows/urn:ietf:params:oauth:grant-type:token-exchange'
path-segment-plural:
- '#/paths/~1healthz'
operation-4xx-response:
- '#/paths/~1healthz/get/responses'
openapi/tags/auth.yaml:
operation-4xx-problem-details-rfc7807:
- '#/components/responses/TokenError'
Expand All @@ -15,10 +16,8 @@ openapi/tags/songs.yaml:
operation-4xx-problem-details-rfc7807:
- '#/components/schemas/SongNotFoundError/allOf/1/properties/type'
- '#/components/schemas/SongNotFoundError/allOf/1/properties/title'
- >-
#/components/responses/UploadSongCannotBeModified/content/application~1problem+json/schema/allOf/1/properties/type
- >-
#/components/responses/UploadSongCannotBeModified/content/application~1problem+json/schema/allOf/1/properties/title
- '#/components/responses/UploadSongCannotBeModified/content/application~1problem+json/schema/allOf/1/properties/type'
- '#/components/responses/UploadSongCannotBeModified/content/application~1problem+json/schema/allOf/1/properties/title'
- '#/components/schemas/InvalidTXTError/allOf/1/properties/type'
- '#/components/schemas/InvalidTXTError/allOf/1/properties/title'
openapi/tags/media.yaml:
Expand All @@ -27,34 +26,22 @@ openapi/tags/media.yaml:
- '#/components/schemas/FileNotFoundError/allOf/1/properties/title'
openapi/common/problem-details.yaml:
operation-4xx-problem-details-rfc7807:
- >-
#/components/responses/UnprocessableEntity/content/application~1problem+json/schema/allOf/1/properties/type
- >-
#/components/responses/UnprocessableEntity/content/application~1problem+json/schema/allOf/1/properties/title
- '#/components/responses/UnprocessableEntity/content/application~1problem+json/schema/allOf/1/properties/type'
- '#/components/responses/UnprocessableEntity/content/application~1problem+json/schema/allOf/1/properties/title'
openapi/tags/uploads.yaml:
operation-4xx-problem-details-rfc7807:
- '#/components/schemas/UploadNotFoundError/allOf/1/properties/type'
- '#/components/schemas/UploadNotFoundError/allOf/1/properties/title'
- >-
#/components/responses/InvalidPathOrUUID/content/application~1problem+json/schema/oneOf/1/allOf/1/properties/type
- >-
#/components/responses/InvalidPathOrUUID/content/application~1problem+json/schema/oneOf/1/allOf/1/properties/title
- >-
#/components/responses/FileOrUploadNotFound/content/application~1problem+json/schema/oneOf/1/allOf/1/properties/type
- >-
#/components/responses/FileOrUploadNotFound/content/application~1problem+json/schema/oneOf/1/allOf/1/properties/title
- '#/components/responses/InvalidPathOrUUID/content/application~1problem+json/schema/oneOf/1/allOf/1/properties/type'
- '#/components/responses/InvalidPathOrUUID/content/application~1problem+json/schema/oneOf/1/allOf/1/properties/title'
- '#/components/responses/FileOrUploadNotFound/content/application~1problem+json/schema/oneOf/1/allOf/1/properties/type'
- '#/components/responses/FileOrUploadNotFound/content/application~1problem+json/schema/oneOf/1/allOf/1/properties/title'
- '#/components/responses/UploadStateError'
openapi/tags/user.yaml:
operation-4xx-problem-details-rfc7807:
- >-
#/components/responses/UsernameNotAvailable/content/application~1problem+json/schema/allOf/1/properties/type
- >-
#/components/responses/UsernameNotAvailable/content/application~1problem+json/schema/allOf/1/properties/title
- >-
#/components/responses/UserNotFound/content/application~1problem+json/schema/allOf/1/properties/type
- >-
#/components/responses/UserNotFound/content/application~1problem+json/schema/allOf/1/properties/title
- >-
#/paths/~1v1~1users~1{id}~1email/post/responses/409/content/application~1problem+json/schema/allOf/1/properties/type
- >-
#/paths/~1v1~1users~1{id}~1email/post/responses/409/content/application~1problem+json/schema/allOf/1/properties/title
- '#/components/responses/UsernameNotAvailable/content/application~1problem+json/schema/allOf/1/properties/type'
- '#/components/responses/UsernameNotAvailable/content/application~1problem+json/schema/allOf/1/properties/title'
- '#/components/responses/UserNotFound/content/application~1problem+json/schema/allOf/1/properties/type'
- '#/components/responses/UserNotFound/content/application~1problem+json/schema/allOf/1/properties/title'
- '#/paths/~1v1~1users~1{id}~1email/post/responses/409/content/application~1problem+json/schema/allOf/1/properties/type'
- '#/paths/~1v1~1users~1{id}~1email/post/responses/409/content/application~1problem+json/schema/allOf/1/properties/title'
14 changes: 14 additions & 0 deletions openapi/common/problem-details.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,20 @@ components:
schema:
$ref: "#/components/schemas/PermissionDeniedError"

NotFound:
x-summary: Not Found
description: |-
The requested resource was not found.
content:
application/problem+json:
schema:
example:
title: "Not Found"
status: 404
instance: "/traces/481CF77B-3099-445C-A789-58F997233681"
allOf:
- $ref: "#/components/schemas/ProblemDetails"

UnprocessableEntity:
x-summary: Unprocessable Entity
description: |-
Expand Down
1 change: 1 addition & 0 deletions openapi/karman.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ x-tagGroups:
- upload
- name: Server Management
tags:
- cron
- server


Expand Down
178 changes: 178 additions & 0 deletions openapi/tags/cron.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
openapi: 3.0.3
info:
title: Background Jobs
version: v1
license:
name: MIT
url: https://opensource.org/license/mit/


tags:
- name: cron
x-displayName: Background Jobs
description: |-
Karman performs various scheduled jobs in the background.
These endpoints offer some management capabilities for application administrators.

Jobs are identified by name.
The following jobs are available:

- `media:prune`: This job deletes media files
- `upload:prune`: This job deletes uploads that have been soft-deleted.
- `upload:enqueue`: This job creates tasks for processing uploads.
If an upload processing task has been lost (e.g. because the redis instance failed)
this job recreates those tasks.
- `song:prune`: This job deletes songs that have been soft-deleted.

The schedule for each job depends on the server settings.
Server admins can also restrict the ability to run these jobs via the API.


paths:
/v1/jobs:
get:
operationId: getJobs
summary: List Jobs
tags: [ cron ]
description: |-
Fetch all background jobs and their respective states.
See [Background Jobs](#tag/cron) for a description of the available jobs.
responses:
200:
x-summary: OK
description: |-
A successful request returns a mapping of jobs to their configurations.
content:
application/json:
example:
media:prune:
name: "media:prune"
enabled: true
active: false
scheduledAt: "2023-08-24T14:15:22Z"
upload:prune:
name: "upload:prune"
enabled: false
active: true
schema:
additionalProperties:
x-additionalPropertiesName: job
type: object
description: |-
Each mapping value describes a single job.
allOf:
- $ref: "#/components/schemas/Job"
401: { $ref: "../common/problem-details.yaml#/components/responses/Unauthorized" }
403: { $ref: "../common/problem-details.yaml#/components/responses/PermissionDenied" }
5XX: { $ref: "../common/problem-details.yaml#/components/responses/UnexpectedError" }

/v1/jobs/{name}:
parameters:
- $ref: "#/components/parameters/JobName"
get:
operationId: getJob
summary: Get Job Status
tags: [ cron ]
description: |-
Get status information about a single job.
See [Background Jobs](#tag/cron) for a description of the available jobs.
responses:
200:
x-summary: OK
description: |-
A successful request returns information about a job.
content:
application/json:
schema: { $ref: "#/components/schemas/Job" }
401: { $ref: "../common/problem-details.yaml#/components/responses/Unauthorized" }
403: { $ref: "../common/problem-details.yaml#/components/responses/PermissionDenied" }
404: { $ref: "../common/problem-details.yaml#/components/responses/NotFound" }
5XX: { $ref: "../common/problem-details.yaml#/components/responses/UnexpectedError" }

/v1/jobs/{name}/start:
parameters:
- $ref: "#/components/parameters/JobName"
post:
operationId: startJob
summary: Start Job
tags: [ cron ]
description: |-
Start a scheduled job manually.
Depending on the job this may or may not effect the next execution date.
If the job is disabled the response will have code 403.
# Empty request body
responses:
202:
x-summary: Accepted
description: |-
The job was started.
This response gives no indication about the time when the job is finished.
Use the `active` field of a job to fetch that information.
401: { $ref: "../common/problem-details.yaml#/components/responses/Unauthorized" }
403: { $ref: "../common/problem-details.yaml#/components/responses/PermissionDenied" }
404: { $ref: "../common/problem-details.yaml#/components/responses/NotFound" }
409:
x-summary: Conflict
description: |-
The task is already running or in a state where it cannot be started.
content:
application/problem+json:
schema:
example:
type: "tag:codello.dev,2020:karman/problems:invalid-job-sate"
title: "Invalid Job State"
status: 409
allOf:
- $ref: "../common/problem-details.yaml#/components/schemas/ProblemDetails"
5XX: { $ref: "../common/problem-details.yaml#/components/responses/UnexpectedError" }


components:
schemas:
Job:
type: object
x-tags: [ cron ]
description: |-
A background Job.
properties:
name:
type: string
example: "media:prune"
description: |-
The name of the job.
Job names are unique and serve as their the primary identifier.
enabled:
type: boolean
example: true
description: |-
Indicates whether this job enabled or not.
A disabled job cannot be triggered manually.
The enabled state may depend on the user performing the request, i.e.
a job can be enabled for one user and disabled for another user.
active:
type: boolean
example: false
description: |-
Indicates whether this job is currently being executed.
scheduledAt:
type: string
format: date-time
example: "2019-08-24T14:15:22Z"
description: |-
The next planned execution date for this job.
This is only the next planned date.
The job may be scheduled at an interval leading to more executions after this date.

If a job does not have a scheduled date (i.e. this field is `null` or absent) the job is not a scheduled job.
You may still be able to trigger the job manually.

parameters:
JobName:
name: name
in: path
required: true
description: |-
The name of the job to fetch.
schema:
type: string
example: "media:prune"
10 changes: 5 additions & 5 deletions openapi/tags/media.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ paths:
400: { $ref: "../common/problem-details.yaml#/components/responses/InvalidUUID" }
401: { $ref: "../common/problem-details.yaml#/components/responses/Unauthorized" }
403: { $ref: "../common/problem-details.yaml#/components/responses/PermissionDenied" }
404: { $ref: "#/components/responses/NotFound" }
404: { $ref: "#/components/responses/SongOrFileNotFound" }
5XX: { $ref: "../common/problem-details.yaml#/components/responses/UnexpectedError" }

put:
Expand Down Expand Up @@ -119,7 +119,7 @@ paths:
400: { $ref: "../common/problem-details.yaml#/components/responses/InvalidUUID" }
401: { $ref: "../common/problem-details.yaml#/components/responses/Unauthorized" }
403: { $ref: "../common/problem-details.yaml#/components/responses/PermissionDenied" }
404: { $ref: "#/components/responses/NotFound" }
404: { $ref: "#/components/responses/SongOrFileNotFound" }
5XX: { $ref: "../common/problem-details.yaml#/components/responses/UnexpectedError" }

put:
Expand Down Expand Up @@ -191,7 +191,7 @@ paths:
400: { $ref: "../common/problem-details.yaml#/components/responses/InvalidUUID" }
401: { $ref: "../common/problem-details.yaml#/components/responses/Unauthorized" }
403: { $ref: "../common/problem-details.yaml#/components/responses/PermissionDenied" }
404: { $ref: "#/components/responses/NotFound" }
404: { $ref: "#/components/responses/SongOrFileNotFound" }
5XX: { $ref: "../common/problem-details.yaml#/components/responses/UnexpectedError" }

put:
Expand Down Expand Up @@ -263,7 +263,7 @@ paths:
400: { $ref: "../common/problem-details.yaml#/components/responses/InvalidUUID" }
401: { $ref: "../common/problem-details.yaml#/components/responses/Unauthorized" }
403: { $ref: "../common/problem-details.yaml#/components/responses/PermissionDenied" }
404: { $ref: "#/components/responses/NotFound" }
404: { $ref: "#/components/responses/SongOrFileNotFound" }
5XX: { $ref: "../common/problem-details.yaml#/components/responses/UnexpectedError" }

put:
Expand Down Expand Up @@ -348,7 +348,7 @@ components:


responses:
NotFound:
SongOrFileNotFound:
x-summary: Not Found
description: |-
Either the song with the specified `uuid` does not exist or it does not have the requested media file.
Expand Down