diff --git a/conversion_helpers.go b/conversion_helpers.go index 486276f..e200466 100644 --- a/conversion_helpers.go +++ b/conversion_helpers.go @@ -348,6 +348,9 @@ func toArchivedTasks(in []*asynq.TaskInfo, pf PayloadFormatter) []*archivedTask type completedTask struct { *baseTask CompletedAt time.Time `json:"completed_at"` + Result string `json:"result"` + // Number of seconds left for retention (i.e. (CompletedAt + ResultTTL) - Now) + ResultTTL int64 `json:"result_ttl_seconds"` } func toCompletedTask(ti *asynq.TaskInfo, pf PayloadFormatter) *completedTask { @@ -360,9 +363,13 @@ func toCompletedTask(ti *asynq.TaskInfo, pf PayloadFormatter) *completedTask { Retried: ti.Retried, LastError: ti.LastErr, } + ttl := ti.CompletedAt.Add(ti.ResultTTL).Sub(time.Now()) return &completedTask{ baseTask: base, CompletedAt: ti.CompletedAt, + ResultTTL: int64(ttl.Seconds()), + // TODO: Use resultFormatter instead + Result: defaultPayloadFormatter.FormatPayload("", ti.Result), } } diff --git a/ui/src/api.ts b/ui/src/api.ts index dcebed4..04fbcf0 100644 --- a/ui/src/api.ts +++ b/ui/src/api.ts @@ -329,6 +329,8 @@ export interface CompletedTask extends BaseTask { max_retry: number; retried: number; completed_at: string; + result: string; + result_ttl_seconds: number } export interface ServerInfo { diff --git a/ui/src/components/CompletedTasksTable.tsx b/ui/src/components/CompletedTasksTable.tsx index 0a6c7a2..a504ba0 100644 --- a/ui/src/components/CompletedTasksTable.tsx +++ b/ui/src/components/CompletedTasksTable.tsx @@ -26,7 +26,12 @@ import TablePaginationActions, { } from "./TablePaginationActions"; import { taskRowsPerPageChange } from "../actions/settingsActions"; import TableActions from "./TableActions"; -import { timeAgo, uuidPrefix } from "../utils"; +import { + durationFromSeconds, + stringifyDuration, + timeAgo, + uuidPrefix, +} from "../utils"; import { usePolling } from "../hooks"; import { CompletedTaskExtended } from "../reducers/tasksReducer"; import { TableColumn } from "../types/table"; @@ -132,8 +137,9 @@ function CompletedTasksTable(props: Props & ReduxProps) { { key: "id", label: "ID", align: "left" }, { key: "type", label: "Type", align: "left" }, { key: "payload", label: "Payload", align: "left" }, - { key: "completed_at", label: "Completed Time", align: "left" }, + { key: "completed_at", label: "Completed", align: "left" }, { key: "result", label: "Result", align: "left" }, + { key: "ttl", label: "TTL", align: "left" }, { key: "actions", label: "Actions", align: "center" }, ]; @@ -310,7 +316,21 @@ function Row(props: RowProps) { {timeAgo(task.completed_at)} - {"TODO: Result data here"} + + + {task.result} + + + + {task.result_ttl_seconds > 0 + ? `${stringifyDuration( + durationFromSeconds(task.result_ttl_seconds) + )} left` + : `expired`} + + ); diff --git a/ui/src/utils.ts b/ui/src/utils.ts index b668a0f..6209853 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -25,17 +25,22 @@ interface Duration { totalSeconds: number; } -// start and end are in milliseconds. -function durationBetween(start: number, end: number): Duration { - const durationInMillisec = start - end; - const totalSeconds = Math.floor(durationInMillisec / 1000); +// Returns a duration from the number of seconds provided. +export function durationFromSeconds(totalSeconds: number): Duration { const hour = Math.floor(totalSeconds / 3600); const minute = Math.floor((totalSeconds - 3600 * hour) / 60); const second = totalSeconds - 3600 * hour - 60 * minute; return { hour, minute, second, totalSeconds }; } -function stringifyDuration(d: Duration): string { +// start and end are in milliseconds. +function durationBetween(start: number, end: number): Duration { + const durationInMillisec = start - end; + const totalSeconds = Math.floor(durationInMillisec / 1000); + return durationFromSeconds(totalSeconds); +} + +export function stringifyDuration(d: Duration): string { if (d.hour > 24) { const n = Math.floor(d.hour / 24); return n + (n === 1 ? " day" : " days");