Change job priority on queue page

This commit is contained in:
Eike Kettner 2020-09-05 16:00:41 +02:00
parent 1dcccbcf7d
commit 06879456a6
10 changed files with 140 additions and 11 deletions
modules
backend/src/main/scala/docspell/backend/ops
common/src/main/scala/docspell/common
restapi/src/main/resources
restserver/src/main/scala/docspell/restserver/routes
store/src/main/scala/docspell/store/records
webapp/src/main/elm

@ -5,8 +5,10 @@ import cats.effect._
import cats.implicits._
import docspell.backend.ops.OJob.{CollectiveQueueState, JobCancelResult}
import docspell.common.Priority
import docspell.common.{Ident, JobState}
import docspell.store.Store
import docspell.store.UpdateResult
import docspell.store.queries.QJob
import docspell.store.records.{RJob, RJobLog}
@ -15,6 +17,8 @@ trait OJob[F[_]] {
def queueState(collective: Ident, maxResults: Int): F[CollectiveQueueState]
def cancelJob(id: Ident, collective: Ident): F[JobCancelResult]
def setPriority(id: Ident, collective: Ident, prio: Priority): F[UpdateResult]
}
object OJob {
@ -56,6 +60,9 @@ object OJob {
.toVector
.map(CollectiveQueueState)
def setPriority(id: Ident, collective: Ident, prio: Priority): F[UpdateResult] =
UpdateResult.fromUpdate(store.transact(RJob.setPriority(id, collective, prio)))
def cancelJob(id: Ident, collective: Ident): F[JobCancelResult] = {
def remove(job: RJob): F[JobCancelResult] =
store.transact(RJob.delete(job.id)) *> JobCancelResult.removed.pure[F]

@ -12,6 +12,8 @@ object JobState {
/** Waiting for being executed. */
case object Waiting extends JobState {}
def waiting: JobState = Waiting
/** A scheduler has picked up this job and will pass it to the next
* free slot.
*/

@ -2167,6 +2167,30 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/BasicResult"
/sec/queue/{id}/priority:
post:
tags: [ Job Queue ]
summary: Change the priority of a waiting job.
description: |
A waiting job can change its priority. If the job is not in
state waiting, this operation fails.
security:
- authTokenHeader: []
parameters:
- $ref: "#/components/parameters/id"
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/JobPriority"
responses:
200:
description: Ok
content:
application/json:
schema:
$ref: "#/components/schemas/BasicResult"
/sec/email/settings/smtp:
get:
tags: [ E-Mail ]
@ -2678,6 +2702,18 @@ paths:
components:
schemas:
JobPriority:
description: |
Transfer the priority of a job.
required:
- priority
properties:
priority:
type: string
format: priority
enum:
- high
- low
IdList:
description:
A list of identifiers.
@ -3512,6 +3548,9 @@ components:
priority:
type: string
format: priority
enum:
- high
- low
state:
type: string
format: jobstate
@ -3744,6 +3783,9 @@ components:
priority:
type: string
format: priority
enum:
- high
- low
folder:
type: string
format: ident

@ -6,9 +6,11 @@ import cats.implicits._
import docspell.backend.BackendApp
import docspell.backend.auth.AuthToken
import docspell.common.Ident
import docspell.restapi.model.JobPriority
import docspell.restserver.conv.Conversions
import org.http4s.HttpRoutes
import org.http4s.circe.CirceEntityDecoder._
import org.http4s.circe.CirceEntityEncoder._
import org.http4s.dsl.Http4sDsl
@ -31,6 +33,13 @@ object JobQueueRoutes {
result <- backend.job.cancelJob(id, user.account.collective)
resp <- Ok(Conversions.basicResult(result))
} yield resp
case req @ POST -> Root / Ident(id) / "priority" =>
for {
prio <- req.as[JobPriority]
res <- backend.job.setPriority(id, user.account.collective, prio.priority)
resp <- Ok(Conversions.basicResult(res, "Job priority changed"))
} yield resp
}
}

@ -231,6 +231,13 @@ object RJob {
)
).update.run
def setPriority(jobId: Ident, jobGroup: Ident, prio: Priority): ConnectionIO[Int] =
updateRow(
table,
and(id.is(jobId), group.is(jobGroup), state.is(JobState.waiting)),
priority.setTo(prio)
).update.run
def getRetries(jobId: Ident): ConnectionIO[Option[Int]] =
selectSimple(List(retries), table, id.is(jobId)).query[Int].option

@ -86,6 +86,7 @@ module Api exposing
, setItemDueDate
, setItemName
, setItemNotes
, setJobPrio
, setTags
, setUnconfirmed
, startClassifier
@ -129,6 +130,7 @@ import Api.Model.ItemLightList exposing (ItemLightList)
import Api.Model.ItemProposals exposing (ItemProposals)
import Api.Model.ItemSearch exposing (ItemSearch)
import Api.Model.ItemUploadMeta exposing (ItemUploadMeta)
import Api.Model.JobPriority exposing (JobPriority)
import Api.Model.JobQueueState exposing (JobQueueState)
import Api.Model.MoveAttachment exposing (MoveAttachment)
import Api.Model.NewFolder exposing (NewFolder)
@ -160,6 +162,7 @@ import Api.Model.UserPass exposing (UserPass)
import Api.Model.VersionInfo exposing (VersionInfo)
import Data.ContactType exposing (ContactType)
import Data.Flags exposing (Flags)
import Data.Priority exposing (Priority)
import File exposing (File)
import Http
import Json.Encode as JsonEncode
@ -1197,6 +1200,21 @@ deleteUser flags user receive =
--- Job Queue
setJobPrio : Flags -> String -> Priority -> (Result Http.Error BasicResult -> msg) -> Cmd msg
setJobPrio flags jobid prio receive =
Http2.authPost
{ url = flags.config.baseUrl ++ "/api/v1/sec/queue/" ++ jobid ++ "/priority"
, account = getAccount flags
, body =
Data.Priority.toName prio
|> String.toLower
|> JobPriority
|> Api.Model.JobPriority.encode
|> Http.jsonBody
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
}
cancelJob : Flags -> String -> (Result Http.Error BasicResult -> msg) -> Cmd msg
cancelJob flags jobid receive =
Http2.authPost

@ -2,6 +2,7 @@ module Data.Priority exposing
( Priority(..)
, all
, fromString
, next
, toName
)
@ -38,6 +39,16 @@ toName lang =
"High"
next : Priority -> Priority
next prio =
case prio of
High ->
Low
Low ->
High
all : List Priority
all =
[ Low, High ]

@ -10,6 +10,7 @@ import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.JobDetail exposing (JobDetail)
import Api.Model.JobQueueState exposing (JobQueueState)
import Comp.YesNoDimmer
import Data.Priority exposing (Priority)
import Http
import Time
import Util.Duration
@ -53,6 +54,7 @@ type Msg
| RequestCancelJob JobDetail
| DimmerMsg JobDetail Comp.YesNoDimmer.Msg
| CancelResp (Result Http.Error BasicResult)
| ChangePrio String Priority
getRunningTime : Model -> JobDetail -> Maybe String

@ -86,6 +86,9 @@ update flags msg model =
CancelResp (Err _) ->
( model, Cmd.none )
ChangePrio id prio ->
( model, Api.setJobPrio flags id prio CancelResp )
getNewTime : Cmd Msg
getNewTime =

@ -143,6 +143,11 @@ dimmerSettings =
renderInfoCard : Model -> JobDetail -> Html Msg
renderInfoCard model job =
let
prio =
Data.Priority.fromString job.priority
|> Maybe.withDefault Data.Priority.Low
in
div
[ classList
[ ( "ui fluid card", True )
@ -194,23 +199,46 @@ renderInfoCard model job =
else
span [ class "invisible" ] []
, div [ class ("ui basic label " ++ jobStateColor job) ]
[ text "Prio"
, div [ class "detail" ]
[ code []
[ Data.Priority.fromString job.priority
|> Maybe.map Data.Priority.toName
|> Maybe.withDefault job.priority
|> text
]
]
]
, div [ class ("ui basic label " ++ jobStateColor job) ]
[ text "Retries"
, div [ class "detail" ]
[ job.retries |> String.fromInt |> text
]
]
, case job.state of
"waiting" ->
a
[ class ("ui basic label " ++ jobStateColor job)
, onClick (ChangePrio job.id (Data.Priority.next prio))
, href "#"
, title "Change priority of this job"
]
[ i [ class "sort numeric up icon" ] []
, text "Prio"
, div [ class "detail" ]
[ code []
[ Data.Priority.fromString job.priority
|> Maybe.map Data.Priority.toName
|> Maybe.withDefault job.priority
|> text
]
]
]
_ ->
div
[ class ("ui basic label " ++ jobStateColor job)
]
[ text "Prio"
, div [ class "detail" ]
[ code []
[ Data.Priority.fromString job.priority
|> Maybe.map Data.Priority.toName
|> Maybe.withDefault job.priority
|> text
]
]
]
]
, jobStateLabel job
, div [ class "ui basic label" ]