Add time remaining to embedding reindex pane (#14279)

* Add function to convert seconds to human readable duration

* Add estimated time remaining to reindexing pane
This commit is contained in:
Josh Hawkins 2024-10-11 08:04:25 -05:00 committed by GitHub
parent 2897afce41
commit ae91fa6a39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 0 deletions

View File

@ -175,6 +175,7 @@ class Embeddings:
"descriptions": 0, "descriptions": 0,
"processed_objects": 0, "processed_objects": 0,
"total_objects": 0, "total_objects": 0,
"time_remaining": 0,
} }
self.requestor.send_data(UPDATE_EMBEDDINGS_REINDEX_PROGRESS, totals) self.requestor.send_data(UPDATE_EMBEDDINGS_REINDEX_PROGRESS, totals)
@ -229,6 +230,13 @@ class Embeddings:
totals["descriptions"], totals["descriptions"],
) )
# Calculate time remaining
elapsed_time = time.time() - st
avg_time_per_event = elapsed_time / totals["processed_objects"]
remaining_events = total_events - totals["processed_objects"]
time_remaining = avg_time_per_event * remaining_events
totals["time_remaining"] = int(time_remaining)
self.requestor.send_data(UPDATE_EMBEDDINGS_REINDEX_PROGRESS, totals) self.requestor.send_data(UPDATE_EMBEDDINGS_REINDEX_PROGRESS, totals)
# Move to the next page # Move to the next page

View File

@ -10,6 +10,7 @@ import { useTimezone } from "@/hooks/use-date-utils";
import { FrigateConfig } from "@/types/frigateConfig"; import { FrigateConfig } from "@/types/frigateConfig";
import { SearchFilter, SearchQuery, SearchResult } from "@/types/search"; import { SearchFilter, SearchQuery, SearchResult } from "@/types/search";
import { ModelState } from "@/types/ws"; import { ModelState } from "@/types/ws";
import { formatSecondsToDuration } from "@/utils/dateUtil";
import SearchView from "@/views/search/SearchView"; import SearchView from "@/views/search/SearchView";
import { useCallback, useEffect, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useState } from "react";
import { LuCheck, LuExternalLink, LuX } from "react-icons/lu"; import { LuCheck, LuExternalLink, LuX } from "react-icons/lu";
@ -282,6 +283,16 @@ export default function Explore() {
/> />
</div> </div>
<div className="flex w-96 flex-col gap-2 py-5"> <div className="flex w-96 flex-col gap-2 py-5">
{reindexProgress.time_remaining >= 0 && (
<div className="mb-3 flex flex-col items-center justify-center gap-1">
<div className="text-primary-variant">
Estimated time remaining:
</div>
{formatSecondsToDuration(
reindexProgress.time_remaining,
) || "Finishing shortly"}
</div>
)}
<div className="flex flex-row items-center justify-center gap-3"> <div className="flex flex-row items-center justify-center gap-3">
<span className="text-primary-variant"> <span className="text-primary-variant">
Thumbnails embedded: Thumbnails embedded:

View File

@ -67,6 +67,7 @@ export type EmbeddingsReindexProgressType = {
descriptions: number; descriptions: number;
processed_objects: number; processed_objects: number;
total_objects: number; total_objects: number;
time_remaining: number;
}; };
export type ToggleableSetting = "ON" | "OFF"; export type ToggleableSetting = "ON" | "OFF";

View File

@ -229,6 +229,23 @@ export const getDurationFromTimestamps = (
return duration; return duration;
}; };
/**
*
* @param seconds - number of seconds to convert into hours, minutes and seconds
* @returns string - formatted duration in hours, minutes and seconds
*/
export const formatSecondsToDuration = (seconds: number): string => {
if (isNaN(seconds) || seconds < 0) {
return "Invalid duration";
}
const duration = intervalToDuration({ start: 0, end: seconds * 1000 });
return formatDuration(duration, {
format: ["hours", "minutes", "seconds"],
delimiter: ", ",
});
};
/** /**
* Adapted from https://stackoverflow.com/a/29268535 this takes a timezone string and * Adapted from https://stackoverflow.com/a/29268535 this takes a timezone string and
* returns the offset of that timezone from UTC in minutes. * returns the offset of that timezone from UTC in minutes.