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");