mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-29 03:16:51 +03:00
report null instead of 0 for a stream with no cached bandwidth sample
This commit is contained in:
+4
-2
@@ -156,11 +156,13 @@ class StorageMaintainer(threading.Thread):
|
||||
"bandwidth", 0
|
||||
),
|
||||
# only streams with segments on disk are reported, so a camera
|
||||
# keeps its sub entry until sub retention expires those segments
|
||||
# keeps its sub entry until sub retention expires those segments.
|
||||
# bandwidth is null rather than 0 when the cache holds no sample
|
||||
# for the stream, since 0 would claim it writes nothing
|
||||
"streams": {
|
||||
stream_type: {
|
||||
"usage": stream_usages[stream_type],
|
||||
"bandwidth": stream_bandwidths.get(stream_type, 0),
|
||||
"bandwidth": stream_bandwidths.get(stream_type),
|
||||
}
|
||||
for stream_type in (STREAM_TYPE_MAIN, STREAM_TYPE_SUB)
|
||||
if stream_usages.get(stream_type)
|
||||
|
||||
@@ -283,6 +283,49 @@ class TestHttp(unittest.TestCase):
|
||||
== MAX_CALCULATED_BANDWIDTH
|
||||
)
|
||||
|
||||
def test_stream_bandwidth_is_none_without_a_cached_sample(self):
|
||||
"""A stream that appears after the bandwidth cache freezes has no estimate.
|
||||
|
||||
Sub stream recording can be toggled on at runtime, so the cache can hold
|
||||
a main-only sample while sub segments are already landing on disk.
|
||||
Reporting 0 there would claim the sub stream costs nothing.
|
||||
"""
|
||||
config = FrigateConfig(**self.minimal_config)
|
||||
storage = StorageMaintainer(config, MagicMock())
|
||||
|
||||
time_keep = datetime.datetime.now().timestamp()
|
||||
for i in range(60):
|
||||
_insert_mock_recording(
|
||||
f"main_{i}.frontdoor",
|
||||
os.path.join(self.test_dir, f"main_{i}.tmp"),
|
||||
time_keep + i * 10,
|
||||
time_keep + i * 10 + 10,
|
||||
seg_size=20,
|
||||
seg_dur=10,
|
||||
)
|
||||
|
||||
# 50 or more segments flips needs_refresh off, freezing the cache
|
||||
storage.calculate_camera_bandwidth()
|
||||
assert storage.camera_storage_stats["front_door"]["needs_refresh"] is False
|
||||
|
||||
for i in range(60):
|
||||
_insert_mock_recording(
|
||||
f"sub_{i}.frontdoor",
|
||||
os.path.join(self.test_dir, f"sub_{i}.tmp"),
|
||||
time_keep + 5000 + i * 10,
|
||||
time_keep + 5000 + i * 10 + 10,
|
||||
seg_size=2,
|
||||
seg_dur=10,
|
||||
stream_type=STREAM_TYPE_SUB,
|
||||
)
|
||||
|
||||
storage.calculate_camera_bandwidth()
|
||||
streams = storage.calculate_camera_usages()["front_door"]["streams"]
|
||||
|
||||
assert streams[STREAM_TYPE_SUB]["usage"] == 120
|
||||
assert streams[STREAM_TYPE_SUB]["bandwidth"] is None
|
||||
assert streams[STREAM_TYPE_MAIN]["bandwidth"] == 7200
|
||||
|
||||
def test_camera_usages_with_no_recordings(self):
|
||||
"""A camera with no segments reports zero usage and no streams."""
|
||||
config = FrigateConfig(**self.minimal_config)
|
||||
|
||||
@@ -204,9 +204,12 @@ export function CombinedStorageGraph({
|
||||
|
||||
const getStreamSplit = useCallback(
|
||||
(row: StorageRow, field: keyof StreamStorage) => {
|
||||
const sub = row.streams?.sub;
|
||||
const mainValue = row.streams?.main?.[field];
|
||||
const subValue = row.streams?.sub?.[field];
|
||||
|
||||
if (!sub) {
|
||||
// omit the split entirely when either side is unknown, rather than
|
||||
// showing a zero that would read as "this stream costs nothing"
|
||||
if (mainValue == null || subValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -216,13 +219,13 @@ export function CombinedStorageGraph({
|
||||
<span className="text-muted-foreground">
|
||||
{t("quality.main", { ns: "components/player" })}
|
||||
</span>{" "}
|
||||
{getUnitSize(row.streams?.main?.[field] ?? 0)}
|
||||
{getUnitSize(mainValue)}
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-muted-foreground">
|
||||
{t("quality.sub", { ns: "components/player" })}
|
||||
</span>{" "}
|
||||
{getUnitSize(sub[field])}
|
||||
{getUnitSize(subValue)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -103,7 +103,7 @@ export type StorageStats = {
|
||||
|
||||
export type StreamStorage = {
|
||||
usage: number;
|
||||
bandwidth: number;
|
||||
bandwidth: number | null;
|
||||
};
|
||||
|
||||
export type CameraStorage = {
|
||||
|
||||
Reference in New Issue
Block a user