code refactoring, enabled memory db persist to fs.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -15,3 +15,4 @@ downloads
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
build/
|
build/
|
||||||
yt-dlp-webui
|
yt-dlp-webui
|
||||||
|
session.dat
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import { RootState, store } from './stores/store'
|
|||||||
import AppBar from './components/AppBar'
|
import AppBar from './components/AppBar'
|
||||||
import Drawer from './components/Drawer'
|
import Drawer from './components/Drawer'
|
||||||
|
|
||||||
import Downloaded from './Downloaded'
|
import Archive from './Archive'
|
||||||
import { formatGiB } from './utils'
|
import { formatGiB } from './utils'
|
||||||
|
|
||||||
function AppContent() {
|
function AppContent() {
|
||||||
@@ -148,7 +148,7 @@ function AppContent() {
|
|||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<DownloadIcon />
|
<DownloadIcon />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary="Downloaded" />
|
<ListItemText primary="Archive" />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to={'/settings'} style={
|
<Link to={'/settings'} style={
|
||||||
@@ -188,7 +188,7 @@ function AppContent() {
|
|||||||
} />
|
} />
|
||||||
<Route path="/archive" element={
|
<Route path="/archive" element={
|
||||||
<Suspense fallback={<CircularProgress />}>
|
<Suspense fallback={<CircularProgress />}>
|
||||||
<Downloaded />
|
<Archive />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
} />
|
} />
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|||||||
@@ -130,7 +130,11 @@ export default function Downloaded() {
|
|||||||
icon={<DeleteForeverIcon />}
|
icon={<DeleteForeverIcon />}
|
||||||
tooltipTitle={`Delete selected`}
|
tooltipTitle={`Delete selected`}
|
||||||
tooltipOpen
|
tooltipOpen
|
||||||
onClick={() => setOpenDialog(true)}
|
onClick={() => {
|
||||||
|
if (selected$.value.length > 0) {
|
||||||
|
setOpenDialog(true)
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</SpeedDial>
|
</SpeedDial>
|
||||||
<Dialog
|
<Dialog
|
||||||
@@ -6,7 +6,7 @@ import { StackableResult } from "./StackableResult"
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
downloads: RPCResult[]
|
downloads: RPCResult[]
|
||||||
abortFunction: Function
|
abortFunction: (id: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DownloadsCardView({ downloads, abortFunction }: Props) {
|
export function DownloadsCardView({ downloads, abortFunction }: Props) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { EightK, FourK, Hd, Sd } from "@mui/icons-material";
|
import { EightK, FourK, Hd, Sd } from '@mui/icons-material'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
@@ -11,9 +11,9 @@ import {
|
|||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Typography
|
Typography
|
||||||
} from "@mui/material";
|
} from '@mui/material'
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react'
|
||||||
import { ellipsis, formatSpeedMiB, roundMiB } from "../utils";
|
import { ellipsis, formatSpeedMiB, roundMiB } from '../utils'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
title: string,
|
title: string,
|
||||||
@@ -97,7 +97,8 @@ export function StackableResult({
|
|||||||
variant="contained"
|
variant="contained"
|
||||||
size="small"
|
size="small"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={stopCallback}>
|
onClick={stopCallback}
|
||||||
|
>
|
||||||
{isCompleted ? "Clear" : "Stop"}
|
{isCompleted ? "Clear" : "Stop"}
|
||||||
</Button>
|
</Button>
|
||||||
</CardActions>
|
</CardActions>
|
||||||
|
|||||||
@@ -108,4 +108,14 @@ func (m *MemoryDB) Restore() {
|
|||||||
feed, _ := os.ReadFile("session.dat")
|
feed, _ := os.ReadFile("session.dat")
|
||||||
session := Session{}
|
session := Session{}
|
||||||
json.Unmarshal(feed, &session)
|
json.Unmarshal(feed, &session)
|
||||||
|
|
||||||
|
for _, proc := range session.Processes {
|
||||||
|
db.table.Store(proc.Id, &Process{
|
||||||
|
id: proc.Id,
|
||||||
|
url: proc.Info.URL,
|
||||||
|
Info: proc.Info,
|
||||||
|
Progress: proc.Progress,
|
||||||
|
mem: m,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ func (p *Process) Kill() error {
|
|||||||
// has been spawned with setPgid = true. To properly kill
|
// has been spawned with setPgid = true. To properly kill
|
||||||
// all subprocesses a SIGTERM need to be sent to the correct
|
// all subprocesses a SIGTERM need to be sent to the correct
|
||||||
// process group
|
// process group
|
||||||
|
if p.proc != nil {
|
||||||
pgid, err := syscall.Getpgid(p.proc.Pid)
|
pgid, err := syscall.Getpgid(p.proc.Pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -179,6 +180,8 @@ func (p *Process) Kill() error {
|
|||||||
|
|
||||||
log.Println("Killed process", p.id)
|
log.Println("Killed process", p.id)
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the available format for this URL
|
// Returns the available format for this URL
|
||||||
|
|||||||
@@ -21,6 +21,13 @@ type DirectoryEntry struct {
|
|||||||
SHASum string `json:"shaSum"`
|
SHASum string `json:"shaSum"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isValidEntry(d fs.DirEntry) bool {
|
||||||
|
return !d.IsDir() &&
|
||||||
|
!strings.HasPrefix(d.Name(), ".") &&
|
||||||
|
!strings.HasSuffix(d.Name(), ".part") &&
|
||||||
|
!strings.HasSuffix(d.Name(), ".ytdl")
|
||||||
|
}
|
||||||
|
|
||||||
func walkDir(root string) (*[]DirectoryEntry, error) {
|
func walkDir(root string) (*[]DirectoryEntry, error) {
|
||||||
files := []DirectoryEntry{}
|
files := []DirectoryEntry{}
|
||||||
|
|
||||||
@@ -28,7 +35,7 @@ func walkDir(root string) (*[]DirectoryEntry, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !d.IsDir() && !strings.HasPrefix(d.Name(), ".") {
|
if isValidEntry(d) {
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
h.Write([]byte(path))
|
h.Write([]byte(path))
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/rpc"
|
"net/rpc"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||||
@@ -18,6 +23,8 @@ import (
|
|||||||
var db MemoryDB
|
var db MemoryDB
|
||||||
|
|
||||||
func RunBlocking(port int, frontend fs.FS) {
|
func RunBlocking(port int, frontend fs.FS) {
|
||||||
|
db.Restore()
|
||||||
|
|
||||||
service := new(Service)
|
service := new(Service)
|
||||||
rpc.Register(service)
|
rpc.Register(service)
|
||||||
|
|
||||||
@@ -73,5 +80,34 @@ func RunBlocking(port int, frontend fs.FS) {
|
|||||||
|
|
||||||
app.Server().StreamRequestBody = true
|
app.Server().StreamRequestBody = true
|
||||||
|
|
||||||
|
go periodicallyPersist()
|
||||||
|
go gracefulShutdown(app)
|
||||||
|
|
||||||
log.Fatal(app.Listen(fmt.Sprintf(":%d", port)))
|
log.Fatal(app.Listen(fmt.Sprintf(":%d", port)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func gracefulShutdown(app *fiber.App) {
|
||||||
|
ctx, stop := signal.NotifyContext(context.Background(),
|
||||||
|
os.Interrupt,
|
||||||
|
syscall.SIGTERM,
|
||||||
|
syscall.SIGQUIT,
|
||||||
|
)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-ctx.Done()
|
||||||
|
log.Println("shutdown signal received")
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
db.Persist()
|
||||||
|
stop()
|
||||||
|
app.ShutdownWithTimeout(time.Second * 5)
|
||||||
|
}()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func periodicallyPersist() {
|
||||||
|
for {
|
||||||
|
db.Persist()
|
||||||
|
time.Sleep(time.Minute * 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,12 +72,15 @@ func (t *Service) Running(args NoArgs, running *Running) error {
|
|||||||
func (t *Service) Kill(args string, killed *string) error {
|
func (t *Service) Kill(args string, killed *string) error {
|
||||||
log.Println("Trying killing process with id", args)
|
log.Println("Trying killing process with id", args)
|
||||||
proc, err := db.Get(args)
|
proc, err := db.Get(args)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if proc != nil {
|
if proc != nil {
|
||||||
err = proc.Kill()
|
err = proc.Kill()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db.Delete(proc.id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user