mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-17 16:50:53 +00:00
Enhancement: update channel card tooltip to use stable 'started_at' timestamp and refactor getStartDate utility
Some checks failed
CI Pipeline / prepare (push) Waiting to run
CI Pipeline / docker (amd64, ubuntu-24.04) (push) Blocked by required conditions
CI Pipeline / docker (arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
CI Pipeline / create-manifest (push) Blocked by required conditions
Build and Push Multi-Arch Docker Image / build-and-push (push) Waiting to run
Frontend Tests / test (push) Waiting to run
Base Image Build / prepare (push) Has been cancelled
Base Image Build / docker (amd64, ubuntu-24.04) (push) Has been cancelled
Base Image Build / docker (arm64, ubuntu-24.04-arm) (push) Has been cancelled
Base Image Build / create-manifest (push) Has been cancelled
Some checks failed
CI Pipeline / prepare (push) Waiting to run
CI Pipeline / docker (amd64, ubuntu-24.04) (push) Blocked by required conditions
CI Pipeline / docker (arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
CI Pipeline / create-manifest (push) Blocked by required conditions
Build and Push Multi-Arch Docker Image / build-and-push (push) Waiting to run
Frontend Tests / test (push) Waiting to run
Base Image Build / prepare (push) Has been cancelled
Base Image Build / docker (amd64, ubuntu-24.04) (push) Has been cancelled
Base Image Build / docker (arm64, ubuntu-24.04-arm) (push) Has been cancelled
Base Image Build / create-manifest (push) Has been cancelled
This commit is contained in:
parent
1d9741a019
commit
594596d4f5
4 changed files with 7 additions and 18 deletions
|
|
@ -114,6 +114,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- **2-second "stream thread did not terminate within timeout" warning on every channel stop.** `_close_socket` in `input/manager.py` was closing the relay pipe read-end (`self.socket`) before killing the ffmpeg process. The stream OS thread blocks in `select()` on that fd; on Linux, closing an fd from another thread while a `select()` is in progress on it does not reliably interrupt the call (POSIX allows this to be undefined). The thread stayed blocked for the full chunk-timeout (5 s), and `stream_thread.join(timeout=2.0)` always expired first. Fixed by killing ffmpeg first: when ffmpeg dies its copy of the relay write-end closes, delivering EOF to `select()` immediately. `self.socket` is closed afterward as cleanup only.
|
||||
- **Duplicate `stop_channel` calls on every channel shutdown.** `StreamGenerator._cleanup` triggered channel shutdown via two parallel paths: `client_manager.remove_client()` (which fires `handle_client_disconnect` on the owning worker, the correct path) and `_schedule_channel_shutdown_if_needed` (which independently spawned a delayed `stop_channel` greenlet). The duplicate call was suppressed by the `_stopping_channels` guard but produced a redundant log entry and unnecessary greenlet on every shutdown. `_schedule_channel_shutdown_if_needed` has been removed; `handle_client_disconnect` is the sole shutdown trigger.
|
||||
- **Concurrent greenlets could re-enter `_close_socket` during `proc.wait()`.** `self.transcode_process` was set to `None` at the end of the `if proc:` block rather than immediately after capturing the reference. Under gevent, `proc.wait(timeout=0.5)` yields the hub, allowing a second greenlet to enter `_close_socket`, find `self.transcode_process` still set, and attempt a second kill+close. `self.transcode_process = None` is now assigned immediately after `proc = self.transcode_process` so concurrent callers see `None` and skip the block.
|
||||
- **Channel card "started at" tooltip jumping by 1 second on every stats poll.** The Stats page channel card tooltip showed the channel start time by computing `Date.now() - uptime * 1000` on every render. Because `uptime` is a server-side elapsed-seconds value recomputed each response, this reconstruction drifted by up to 1 second per tick. The basic channel info path now emits `started_at` (the raw Unix timestamp from Redis) alongside `uptime`, matching what the detailed stats path already sent. The frontend `getStartDate` helper now accepts the stable `started_at` timestamp directly, so the displayed wall-clock time is fixed from the first poll and never changes.
|
||||
|
||||
### Performance
|
||||
|
||||
|
|
|
|||
|
|
@ -399,7 +399,8 @@ class ChannelStatus:
|
|||
'owner': metadata.get(ChannelMetadataField.OWNER),
|
||||
'buffer_index': int(buffer_index_value) if buffer_index_value else 0,
|
||||
'client_count': client_count,
|
||||
'uptime': uptime
|
||||
'uptime': uptime,
|
||||
'started_at': created_at if created_at > 0 else None,
|
||||
}
|
||||
|
||||
channel_name = metadata.get(ChannelMetadataField.CHANNEL_NAME)
|
||||
|
|
|
|||
|
|
@ -615,7 +615,7 @@ const StreamConnectionCard = ({
|
|||
|
||||
<Group mt={10}>
|
||||
<Box>
|
||||
<Tooltip label={getStartDate(uptime)}>
|
||||
<Tooltip label={getStartDate(channel.started_at)}>
|
||||
<Center>
|
||||
<Timer pr={5} />
|
||||
{toFriendlyDuration(uptime, 'seconds')}
|
||||
|
|
|
|||
|
|
@ -17,22 +17,9 @@ export const getBufferingSpeedThreshold = (proxySetting) => {
|
|||
return 1.0; // Default fallback
|
||||
};
|
||||
|
||||
export const getStartDate = (uptime) => {
|
||||
// Get the current date and time
|
||||
const currentDate = new Date();
|
||||
// Calculate the start date by subtracting uptime (in milliseconds)
|
||||
const startDate = new Date(currentDate.getTime() - uptime * 1000);
|
||||
// Format the date as a string (you can adjust the format as needed)
|
||||
return startDate.toLocaleString({
|
||||
weekday: 'short', // optional, adds day of the week
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
hour12: true, // 12-hour format with AM/PM
|
||||
});
|
||||
export const getStartDate = (startedAt) => {
|
||||
if (!startedAt) return 'Unknown';
|
||||
return new Date(startedAt * 1000).toLocaleString();
|
||||
};
|
||||
|
||||
export const getM3uAccountsMap = (m3uAccounts) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue