This is a large scale refactor to run all DB transaction code
asynchronsouly. At it's core, better-sqlite3 is a synchronous DB
library. Newer versions disallow transaction code that returns Promises
completely. As such, we've been stuck on older code (and this is
blocking other things, like NodeJS version bumps because of binary
interface changes).
Here we translate all kysely transaction code to Drizzle, because only
the latter supports synchronous execution of queries. This includes a
ton of DB migration code, since changing that completely to something
Drizzle-first is a much larger undertaking that will be tackled in a
follow-up.
This change should unblock the following:
1. Bumping better-sqlite3
2. Bumping nodejs version bumps
3. Paves the way towards Drizzle-only migrations
4. Will allow us to switch over from sync => async results using Drizzle
builders more easily in the future, should we decide to change the
underlying sqlite driver.
The segmentsToKeepBefore buffer could extend the playlist window below
#highestDeletedBelow, causing the playlist to reference segment files
that had already been deleted from disk. Clients requesting those
segments would get 404s.
Add a segmentFloor option to FilterBeforeSegmentNumber that acts as a
hard lower bound for minSeg, and pass #highestDeletedBelow as the floor
from HlsSession.trimPlaylist().
When endSession() stops a session, the run() loop exits asynchronously
and unconditionally called scheduleCleanup(), setting a 15-second timer.
If a new session was created for the same channel within that window, the
old timer's cleanup handler would delete the new session from the map —
causing 404s on subsequent playlist requests.
Three fixes applied:
- Cancel pending cleanup timers in Session.stop() so they never fire
after the session is explicitly stopped
- Skip scheduleCleanup() in HlsSession.run() when state is already
'stopped' (the stop path already handled cleanup)
- Guard 'cleanup' and 'stop' event handlers in SessionManager to verify
the session in the map is the same instance before deleting
* fix: improve user experience of channel overview on mobile
Added:
- Scrollable tabs to view media
- Changed heading sizes
- Scrollable tabs on program details
- Fixed bullet being added to end incorrectly
- Improved program info ux
- Fixed an issue with `useState` inside of `useEffect`
* fix: stack channel icon, name and number
---------
Co-authored-by: Corey Vaillancourt <coreyjv@gmail.com>
The movie (and music video / other video)counts in the channel
overview were inflated because the same program was counted
once per lineup occurrence rather than once per unique program.
Episodes and tracks were unaffected since they already counted unique
shows/artists.
Adding uniqBy(uuid) before the groupBy fixes the count for
all tab types.
Fixes#1634.
Co-authored-by: Corey Vaillancourt <coreyjv@gmail.com>
* fix(search): render "starts with" operator as < in filter string
Add missing entry to `indexOperatorToSyntax` so that
`searchFilterToString`
converts the `starts with` API operator back to `<` instead of
displaying
the literal string "starts with" in the filter box.
Add unit tests to prevent regression.
Fixes#1760
* refactor: use helper method in test
---------
Co-authored-by: Corey Vaillancourt <coreyjv@gmail.com>