Skip to content

Commit a0a7a51

Browse files
authored
Add 'until' to API routes that list things (#752)
1 parent 2343b10 commit a0a7a51

6 files changed

Lines changed: 132 additions & 65 deletions

File tree

app-e2e/src/Test/E2E/Support/Client.purs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ getJobsWith filter = do
122122
includeCompleted = case filter of
123123
ActiveOnly -> Just false
124124
IncludeCompleted -> Just true
125-
route = Jobs { since: Nothing, include_completed: includeCompleted }
125+
route = Jobs { since: Nothing, until: Nothing, order: Nothing, include_completed: includeCompleted }
126126
liftAff $ get (CJ.array V1.jobCodec) clientConfig.baseUrl (printRoute route)
127127

128128
-- | Get the list of jobs (includes completed jobs)
@@ -133,15 +133,15 @@ getJobs = getJobsWith IncludeCompleted
133133
getJob :: JobId -> Maybe LogLevel -> Maybe DateTime -> E2E Job
134134
getJob jobId level since = do
135135
{ clientConfig } <- ask
136-
let route = Job jobId { level, since }
136+
let route = Job jobId { level, since, until: Nothing, order: Nothing }
137137
liftAff $ get V1.jobCodec clientConfig.baseUrl (printRoute route)
138138

139139
-- | Try to get a specific job by ID, returning Left on HTTP/parse errors.
140140
-- | Use this when testing error responses (e.g., expecting 404).
141141
tryGetJob :: JobId -> Maybe LogLevel -> Maybe DateTime -> E2E (Either ClientError Job)
142142
tryGetJob jobId level since = do
143143
{ clientConfig } <- ask
144-
let route = Job jobId { level, since }
144+
let route = Job jobId { level, since, until: Nothing, order: Nothing }
145145
liftAff $ tryGet V1.jobCodec clientConfig.baseUrl (printRoute route)
146146

147147
-- | Check if the server is healthy

app/src/App/Effect/Db.purs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Registry.App.Prelude
55
import Data.Array as Array
66
import Data.DateTime (DateTime)
77
import Data.String as String
8-
import Registry.API.V1 (Job, JobId, LogLevel, LogLine)
8+
import Registry.API.V1 (Job, JobId, LogLevel, LogLine, SortOrder)
99
import Registry.App.Effect.Log (LOG)
1010
import Registry.App.Effect.Log as Log
1111
import Registry.App.SQLite (FinishJob, InsertMatrixJob, InsertPackageSetJob, InsertPublishJob, InsertTransferJob, InsertUnpublishJob, MatrixJobDetails, PackageSetJobDetails, PublishJobDetails, SQLite, SelectJobRequest, SelectJobsRequest, StartJob, TransferJobDetails, UnpublishJobDetails)
@@ -45,7 +45,7 @@ data Db a
4545
| SelectTransferJob PackageName (Either String (Maybe TransferJobDetails) -> a)
4646
| SelectPackageSetJobByPayload PackageSetOperation (Either String (Maybe PackageSetJobDetails) -> a)
4747
| InsertLogLine LogLine a
48-
| SelectLogsByJob JobId LogLevel DateTime (Array LogLine -> a)
48+
| SelectLogsByJob JobId LogLevel DateTime DateTime SortOrder (Array LogLine -> a)
4949
| ResetIncompleteJobs (Array JobId -> a)
5050

5151
derive instance Functor Db
@@ -61,8 +61,8 @@ insertLog :: forall r. LogLine -> Run (DB + r) Unit
6161
insertLog log = Run.lift _db (InsertLogLine log unit)
6262

6363
-- | Select all logs for a given job, filtered by loglevel.
64-
selectLogsByJob :: forall r. JobId -> LogLevel -> DateTime -> Run (DB + r) (Array LogLine)
65-
selectLogsByJob jobId logLevel since = Run.lift _db (SelectLogsByJob jobId logLevel since identity)
64+
selectLogsByJob :: forall r. JobId -> LogLevel -> DateTime -> DateTime -> SortOrder -> Run (DB + r) (Array LogLine)
65+
selectLogsByJob jobId logLevel since until order = Run.lift _db (SelectLogsByJob jobId logLevel since until order identity)
6666

6767
-- | Set a job in the database to the 'finished' state.
6868
finishJob :: forall r. FinishJob -> Run (DB + r) Unit
@@ -228,8 +228,8 @@ handleSQLite env = case _ of
228228
Run.liftEffect $ SQLite.insertLogLine env.db log
229229
pure next
230230

231-
SelectLogsByJob jobId logLevel since reply -> do
232-
{ fail, success } <- Run.liftEffect $ SQLite.selectLogsByJob env.db jobId logLevel since
231+
SelectLogsByJob jobId logLevel since until order reply -> do
232+
{ fail, success } <- Run.liftEffect $ SQLite.selectLogsByJob env.db jobId logLevel since until order
233233
unless (Array.null fail) do
234234
Log.warn $ "Some logs are not readable: " <> String.joinWith "\n" fail
235235
pure $ reply success

app/src/App/SQLite.js

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -168,43 +168,44 @@ export const selectPackageSetJobByPayloadImpl = (db, payload) => {
168168
return stmt.get(payload);
169169
};
170170

171-
const _selectJobs = (db, { table, since, includeCompleted }) => {
171+
const _selectJobs = (db, { table, since, until, includeCompleted, order }) => {
172172
let query = `
173173
SELECT job.*, info.*
174174
FROM ${table} job
175175
JOIN ${JOB_INFO_TABLE} info ON job.jobId = info.jobId
176-
WHERE info.createdAt >= ?
176+
WHERE info.createdAt >= ? AND info.createdAt < ?
177177
`;
178-
let params = [since];
178+
const params = [since, until];
179179

180180
if (includeCompleted === false) {
181181
query += ` AND info.finishedAt IS NULL`;
182182
}
183183

184-
query += ` ORDER BY info.createdAt ASC LIMIT 100`;
184+
const dir = order === 'DESC' ? 'DESC' : 'ASC';
185+
query += ` ORDER BY info.createdAt ${dir} LIMIT 100`;
185186
const stmt = db.prepare(query);
186187

187188
return stmt.all(...params);
188189
}
189190

190-
export const selectPublishJobsImpl = (db, since, includeCompleted) => {
191-
return _selectJobs(db, { table: PUBLISH_JOBS_TABLE, since, includeCompleted });
191+
export const selectPublishJobsImpl = (db, since, until, includeCompleted, order) => {
192+
return _selectJobs(db, { table: PUBLISH_JOBS_TABLE, since, until, includeCompleted, order });
192193
};
193194

194-
export const selectUnpublishJobsImpl = (db, since, includeCompleted) => {
195-
return _selectJobs(db, { table: UNPUBLISH_JOBS_TABLE, since, includeCompleted });
195+
export const selectUnpublishJobsImpl = (db, since, until, includeCompleted, order) => {
196+
return _selectJobs(db, { table: UNPUBLISH_JOBS_TABLE, since, until, includeCompleted, order });
196197
};
197198

198-
export const selectTransferJobsImpl = (db, since, includeCompleted) => {
199-
return _selectJobs(db, { table: TRANSFER_JOBS_TABLE, since, includeCompleted });
199+
export const selectTransferJobsImpl = (db, since, until, includeCompleted, order) => {
200+
return _selectJobs(db, { table: TRANSFER_JOBS_TABLE, since, until, includeCompleted, order });
200201
};
201202

202-
export const selectMatrixJobsImpl = (db, since, includeCompleted) => {
203-
return _selectJobs(db, { table: MATRIX_JOBS_TABLE, since, includeCompleted });
203+
export const selectMatrixJobsImpl = (db, since, until, includeCompleted, order) => {
204+
return _selectJobs(db, { table: MATRIX_JOBS_TABLE, since, until, includeCompleted, order });
204205
};
205206

206-
export const selectPackageSetJobsImpl = (db, since, includeCompleted) => {
207-
return _selectJobs(db, { table: PACKAGE_SET_JOBS_TABLE, since, includeCompleted });
207+
export const selectPackageSetJobsImpl = (db, since, until, includeCompleted, order) => {
208+
return _selectJobs(db, { table: PACKAGE_SET_JOBS_TABLE, since, until, includeCompleted, order });
208209
};
209210

210211
export const startJobImpl = (db, args) => {
@@ -258,13 +259,12 @@ export const insertLogLineImpl = (db, logLine) => {
258259
return stmt.run(logLine);
259260
};
260261

261-
export const selectLogsByJobImpl = (db, jobId, logLevel, since) => {
262-
let query = `
262+
export const selectLogsByJobImpl = (db, jobId, logLevel, since, until, order) => {
263+
const dir = order === 'DESC' ? 'DESC' : 'ASC';
264+
const stmt = db.prepare(`
263265
SELECT * FROM ${LOGS_TABLE}
264-
WHERE jobId = ? AND level >= ? AND timestamp >= ?
265-
ORDER BY timestamp ASC LIMIT 100
266-
`;
267-
268-
const stmt = db.prepare(query);
269-
return stmt.all(jobId, logLevel, since);
266+
WHERE jobId = ? AND level >= ? AND timestamp >= ? AND timestamp < ?
267+
ORDER BY timestamp ${dir} LIMIT 100
268+
`);
269+
return stmt.all(jobId, logLevel, since, until);
270270
};

app/src/App/SQLite.purs

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ import Data.Function (on)
5757
import Data.Nullable (notNull, null)
5858
import Data.Nullable as Nullable
5959
import Data.UUID.Random as UUID
60-
import Effect.Uncurried (EffectFn1, EffectFn2, EffectFn3, EffectFn4)
60+
import Effect.Uncurried (EffectFn1, EffectFn2, EffectFn5, EffectFn6)
6161
import Effect.Uncurried as Uncurried
6262
import Record as Record
63-
import Registry.API.V1 (Job(..), JobId(..), LogLevel(..), LogLine)
63+
import Registry.API.V1 (Job(..), JobId(..), LogLevel(..), LogLine, SortOrder(..))
6464
import Registry.API.V1 as API.V1
6565
import Registry.API.V1 as V1
6666
import Registry.Internal.Codec as Internal.Codec
@@ -193,13 +193,15 @@ toSuccess success = case success of
193193
type SelectJobRequest =
194194
{ level :: Maybe LogLevel
195195
, since :: DateTime
196+
, until :: DateTime
197+
, order :: SortOrder
196198
, jobId :: JobId
197199
}
198200

199201
selectJob :: SQLite -> SelectJobRequest -> Effect { unreadableLogs :: Array String, job :: Either String (Maybe Job) }
200-
selectJob db { level: maybeLogLevel, since, jobId: JobId jobId } = do
202+
selectJob db { level: maybeLogLevel, since, until, order, jobId: JobId jobId } = do
201203
let logLevel = fromMaybe Info maybeLogLevel
202-
{ fail: unreadableLogs, success: logs } <- selectLogsByJob db (JobId jobId) logLevel since
204+
{ fail: unreadableLogs, success: logs } <- selectLogsByJob db (JobId jobId) logLevel since until order
203205
-- Failing to decode a log should not prevent us from returning a job, so we pass
204206
-- failures through to be handled by application code
205207
job <- runExceptT $ firstJust
@@ -263,11 +265,13 @@ selectJob db { level: maybeLogLevel, since, jobId: JobId jobId } = do
263265

264266
type SelectJobsRequest =
265267
{ since :: DateTime
268+
, until :: DateTime
269+
, order :: SortOrder
266270
, includeCompleted :: Boolean
267271
}
268272

269273
selectJobs :: SQLite -> SelectJobsRequest -> Effect { failed :: Array String, jobs :: Array Job }
270-
selectJobs db { since, includeCompleted } = do
274+
selectJobs db { since, until, order, includeCompleted } = do
271275
publishJobs <- selectPublishJobs
272276
unpublishJobs <- selectUnpublishJobs
273277
transferJobs <- selectTransferJobs
@@ -276,27 +280,34 @@ selectJobs db { since, includeCompleted } = do
276280
let
277281
{ fail: failedJobs, success: allJobs } = partitionEithers
278282
(publishJobs <> unpublishJobs <> transferJobs <> matrixJobs <> packageSetJobs)
279-
pure { failed: failedJobs, jobs: take 100 $ sortBy (compare `on` (V1.jobInfo >>> _.createdAt)) allJobs }
283+
cmp = case order of
284+
ASC -> compare `on` (V1.jobInfo >>> _.createdAt)
285+
DESC -> flip compare `on` (V1.jobInfo >>> _.createdAt)
286+
pure { failed: failedJobs, jobs: take 100 $ sortBy cmp allJobs }
280287

281288
where
289+
sinceStr = DateTime.format Internal.Format.iso8601DateTime since
290+
untilStr = DateTime.format Internal.Format.iso8601DateTime until
291+
orderStr = V1.printSortOrder order
292+
282293
selectPublishJobs = do
283-
jobs <- Uncurried.runEffectFn3 selectPublishJobsImpl db (DateTime.format Internal.Format.iso8601DateTime since) includeCompleted
294+
jobs <- Uncurried.runEffectFn5 selectPublishJobsImpl db sinceStr untilStr includeCompleted orderStr
284295
pure $ map (map (PublishJob <<< Record.merge { logs: [], jobType: Proxy :: _ "publish" }) <<< publishJobDetailsFromJSRep) jobs
285296

286297
selectUnpublishJobs = do
287-
jobs <- Uncurried.runEffectFn3 selectUnpublishJobsImpl db (DateTime.format Internal.Format.iso8601DateTime since) includeCompleted
298+
jobs <- Uncurried.runEffectFn5 selectUnpublishJobsImpl db sinceStr untilStr includeCompleted orderStr
288299
pure $ map (map (UnpublishJob <<< Record.merge { logs: [], jobType: Proxy :: _ "unpublish" }) <<< unpublishJobDetailsFromJSRep) jobs
289300

290301
selectTransferJobs = do
291-
jobs <- Uncurried.runEffectFn3 selectTransferJobsImpl db (DateTime.format Internal.Format.iso8601DateTime since) includeCompleted
302+
jobs <- Uncurried.runEffectFn5 selectTransferJobsImpl db sinceStr untilStr includeCompleted orderStr
292303
pure $ map (map (TransferJob <<< Record.merge { logs: [], jobType: Proxy :: _ "transfer" }) <<< transferJobDetailsFromJSRep) jobs
293304

294305
selectMatrixJobs = do
295-
jobs <- Uncurried.runEffectFn3 selectMatrixJobsImpl db (DateTime.format Internal.Format.iso8601DateTime since) includeCompleted
306+
jobs <- Uncurried.runEffectFn5 selectMatrixJobsImpl db sinceStr untilStr includeCompleted orderStr
296307
pure $ map (map (MatrixJob <<< Record.merge { logs: [], jobType: Proxy :: _ "matrix" }) <<< matrixJobDetailsFromJSRep) jobs
297308

298309
selectPackageSetJobs = do
299-
jobs <- Uncurried.runEffectFn3 selectPackageSetJobsImpl db (DateTime.format Internal.Format.iso8601DateTime since) includeCompleted
310+
jobs <- Uncurried.runEffectFn5 selectPackageSetJobsImpl db sinceStr untilStr includeCompleted orderStr
300311
pure $ map (map (PackageSetJob <<< Record.merge { logs: [], jobType: Proxy :: _ "packageset" }) <<< packageSetJobDetailsFromJSRep) jobs
301312

302313
--------------------------------------------------------------------------------
@@ -352,7 +363,7 @@ type SelectPublishParams =
352363

353364
foreign import selectPublishJobImpl :: EffectFn2 SQLite SelectPublishParams (Nullable JSPublishJobDetails)
354365

355-
foreign import selectPublishJobsImpl :: EffectFn3 SQLite String Boolean (Array JSPublishJobDetails)
366+
foreign import selectPublishJobsImpl :: EffectFn5 SQLite String String Boolean String (Array JSPublishJobDetails)
356367

357368
selectNextPublishJob :: SQLite -> Effect (Either String (Maybe PublishJobDetails))
358369
selectNextPublishJob db = do
@@ -452,7 +463,7 @@ type SelectUnpublishParams =
452463

453464
foreign import selectUnpublishJobImpl :: EffectFn2 SQLite SelectUnpublishParams (Nullable JSUnpublishJobDetails)
454465

455-
foreign import selectUnpublishJobsImpl :: EffectFn3 SQLite String Boolean (Array JSUnpublishJobDetails)
466+
foreign import selectUnpublishJobsImpl :: EffectFn5 SQLite String String Boolean String (Array JSUnpublishJobDetails)
456467

457468
selectNextUnpublishJob :: SQLite -> Effect (Either String (Maybe UnpublishJobDetails))
458469
selectNextUnpublishJob db = do
@@ -550,7 +561,7 @@ type SelectTransferParams = { jobId :: Nullable String, packageName :: Nullable
550561

551562
foreign import selectTransferJobImpl :: EffectFn2 SQLite SelectTransferParams (Nullable JSTransferJobDetails)
552563

553-
foreign import selectTransferJobsImpl :: EffectFn3 SQLite String Boolean (Array JSTransferJobDetails)
564+
foreign import selectTransferJobsImpl :: EffectFn5 SQLite String String Boolean String (Array JSTransferJobDetails)
554565

555566
selectNextTransferJob :: SQLite -> Effect (Either String (Maybe TransferJobDetails))
556567
selectNextTransferJob db = do
@@ -686,7 +697,7 @@ matrixJobDetailsFromJSRep { jobId, packageName, packageVersion, compilerVersion,
686697

687698
foreign import selectMatrixJobImpl :: EffectFn2 SQLite (Nullable String) (Nullable JSMatrixJobDetails)
688699

689-
foreign import selectMatrixJobsImpl :: EffectFn3 SQLite String Boolean (Array JSMatrixJobDetails)
700+
foreign import selectMatrixJobsImpl :: EffectFn5 SQLite String String Boolean String (Array JSMatrixJobDetails)
690701

691702
selectNextMatrixJob :: SQLite -> Effect (Either String (Maybe MatrixJobDetails))
692703
selectNextMatrixJob db = do
@@ -734,7 +745,7 @@ foreign import selectPackageSetJobImpl :: EffectFn2 SQLite (Nullable String) (Nu
734745

735746
foreign import selectPackageSetJobByPayloadImpl :: EffectFn2 SQLite String (Nullable JSPackageSetJobDetails)
736747

737-
foreign import selectPackageSetJobsImpl :: EffectFn3 SQLite String Boolean (Array JSPackageSetJobDetails)
748+
foreign import selectPackageSetJobsImpl :: EffectFn5 SQLite String String Boolean String (Array JSPackageSetJobDetails)
738749

739750
selectNextPackageSetJob :: SQLite -> Effect (Either String (Maybe PackageSetJobDetails))
740751
selectNextPackageSetJob db = do
@@ -814,18 +825,22 @@ foreign import insertLogLineImpl :: EffectFn2 SQLite JSLogLine Unit
814825
insertLogLine :: SQLite -> LogLine -> Effect Unit
815826
insertLogLine db = Uncurried.runEffectFn2 insertLogLineImpl db <<< logLineToJSRep
816827

817-
foreign import selectLogsByJobImpl :: EffectFn4 SQLite String Int String (Array JSLogLine)
828+
foreign import selectLogsByJobImpl :: EffectFn6 SQLite String Int String String String (Array JSLogLine)
818829

819830
-- | Select all logs for a given job at or above the indicated log level. To get all
820-
-- | logs, pass the DEBUG log level.
821-
selectLogsByJob :: SQLite -> JobId -> LogLevel -> DateTime -> Effect { fail :: Array String, success :: Array LogLine }
822-
selectLogsByJob db jobId level since = do
823-
let timestamp = DateTime.format Internal.Format.iso8601DateTime since
831+
-- | logs, pass the DEBUG log level. The since and until parameters define a
832+
-- | half-open [since, until) time window.
833+
selectLogsByJob :: SQLite -> JobId -> LogLevel -> DateTime -> DateTime -> SortOrder -> Effect { fail :: Array String, success :: Array LogLine }
834+
selectLogsByJob db jobId level since until order = do
835+
let sinceTimestamp = DateTime.format Internal.Format.iso8601DateTime since
836+
let untilTimestamp = DateTime.format Internal.Format.iso8601DateTime until
824837
jsLogLines <-
825-
Uncurried.runEffectFn4
838+
Uncurried.runEffectFn6
826839
selectLogsByJobImpl
827840
db
828841
(un JobId jobId)
829842
(API.V1.logLevelToPriority level)
830-
timestamp
843+
sinceTimestamp
844+
untilTimestamp
845+
(V1.printSortOrder order)
831846
pure $ partitionEithers $ map logLineFromJSRep jsLogLines

app/src/App/Server/Router.purs

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,14 @@ import Registry.App.Prelude hiding ((/))
55
import Data.Codec.JSON as CJ
66
import Data.Date as Date
77
import Data.DateTime (DateTime(..))
8-
import Data.DateTime as DateTime
98
import Data.Enum as Enum
10-
import Data.Time.Duration (Hours(..), negateDuration)
119
import Effect.Aff as Aff
1210
import Effect.Class.Console as Console
1311
import HTTPurple (Method(..), Request, Response)
1412
import HTTPurple as HTTPurple
1513
import HTTPurple.Status as Status
1614
import Partial.Unsafe (unsafePartial)
17-
import Registry.API.V1 (Route(..))
15+
import Registry.API.V1 (Route(..), SortOrder(..))
1816
import Registry.API.V1 as V1
1917
import Registry.App.API as API
2018
import Registry.App.Auth as Auth
@@ -43,7 +41,7 @@ runRouter env = do
4341
, port
4442
}
4543
{ route: V1.routes
46-
, router: runServer
44+
, router: corsMiddleware runServer
4745
}
4846
where
4947
runServer :: Request Route -> Aff Response
@@ -55,6 +53,27 @@ runRouter env = do
5553
HTTPurple.badRequest (Aff.message error)
5654
Right response -> pure response
5755

56+
-- | CORS middleware that wraps the router.
57+
-- | - OPTIONS requests return a 204 preflight response
58+
-- | - All other responses have CORS headers appended
59+
corsMiddleware :: (Request Route -> Aff Response) -> Request Route -> Aff Response
60+
corsMiddleware next request = case request.method of
61+
Options ->
62+
HTTPurple.emptyResponse' Status.noContent preflightHeaders
63+
_ -> do
64+
response <- next request
65+
pure $ response { headers = response.headers <> corsHeaders }
66+
where
67+
corsHeaders =
68+
HTTPurple.header "Access-Control-Allow-Origin" "*"
69+
<> HTTPurple.header "Access-Control-Allow-Methods" "GET, HEAD, POST, OPTIONS"
70+
<> HTTPurple.header "Vary" "Origin"
71+
72+
preflightHeaders =
73+
corsHeaders
74+
<> HTTPurple.header "Access-Control-Allow-Headers" "Content-Type"
75+
<> HTTPurple.header "Access-Control-Max-Age" "86400"
76+
5877
router :: Request Route -> Run ServerEffects Response
5978
router { route, method, body } = HTTPurple.usingCont case route, method of
6079
Publish, Post -> do
@@ -112,22 +131,30 @@ router { route, method, body } = HTTPurple.usingCont case route, method of
112131
_ ->
113132
HTTPurple.badRequest "Expected transfer operation."
114133

115-
Jobs { since, include_completed }, Get -> do
134+
Jobs { since: since', until: until', order: order', include_completed }, Get -> do
116135
now <- liftEffect nowUTC
117-
let oneHourAgo = fromMaybe now $ DateTime.adjust (negateDuration (Hours 1.0)) now
136+
let since = fromMaybe registryLaunch since'
137+
let until = fromMaybe now until'
138+
let order = fromMaybe ASC order'
118139
lift
119140
( Run.Except.runExcept $ Db.selectJobs
120141
{ includeCompleted: fromMaybe false include_completed
121-
, since: fromMaybe oneHourAgo since
142+
, since
143+
, until
144+
, order
122145
}
123146
) >>= case _ of
124147
Left err -> do
125148
lift $ Log.error $ "Error while fetching jobs: " <> err
126149
HTTPurple.internalServerError $ "Error while fetching jobs: " <> err
127150
Right jobs -> jsonOk (CJ.array V1.jobCodec) jobs
128151

129-
Job jobId { level: maybeLogLevel, since }, Get -> do
130-
lift (Run.Except.runExcept $ Db.selectJob { jobId, level: maybeLogLevel, since: fromMaybe registryLaunch since }) >>= case _ of
152+
Job jobId { level: maybeLogLevel, since: since', until: until', order: order' }, Get -> do
153+
now <- liftEffect nowUTC
154+
let since = fromMaybe registryLaunch since'
155+
let until = fromMaybe now until'
156+
let order = fromMaybe ASC order'
157+
lift (Run.Except.runExcept $ Db.selectJob { jobId, level: maybeLogLevel, since, until, order }) >>= case _ of
131158
Left err -> do
132159
lift $ Log.error $ "Error while fetching job: " <> err
133160
HTTPurple.internalServerError $ "Error while fetching job: " <> err

0 commit comments

Comments
 (0)