fix: admin/monitor: inconsistent progress
Massimo Melina committed
Jul 12, 2023 at 00:30 UTC
5c0156bae38f06c9e721ea0becdf495e2bc6768e
6 files changed
+11
-9
admin/src/MonitorPage.ts
+1
-1
@@ -146,7 +146,7 @@ function Connections() {
146
return h(Fragment, {},
147
row.op && h(IconProgress, {
148
icon: row.op === 'upload' ? Upload : Download,
149
- progress: row.opProgress,
149
+ progress: row.opProgress ?? row.opOffset,
150
offset: row.opOffset,
151
addTitle: row.opTotal && h('div', {}, "Total: " + formatBytes(row.opTotal)),
152
sx: { mr: 1 }
src/api.monitor.ts
+3
-1
@@ -2,7 +2,7 @@
2
3
import _ from 'lodash'
4
import { Connection, getConnections } from './connections'
5
-import { pendingPromise, typedKeys, wait } from './misc'
5
+import { isLocalHost, pendingPromise, typedKeys, wait } from './misc'
6
import { ApiHandlers, SendListReadable } from './apiMiddleware'
7
import Koa from 'koa'
8
import { totalGot, totalInSpeed, totalOutSpeed, totalSent } from './throttler'
@@ -52,6 +52,8 @@ const apis: ApiHandlers = {
52
Object.assign(change, fromCtx(change.ctx))
53
change.ctx = undefined
54
}
55
+ if (change.opProgress)
56
+ change.opProgress = _.round(change.opProgress, 3)
57
// avoid sending non-changes
58
const last = conn[sent]
59
for (const k of typedKeys(change))
src/connections.ts
+2
-3
@@ -59,9 +59,8 @@ export function socket2connection(socket: Socket) {
59
}
60
61
export function updateConnection(conn: Connection, change: Partial<Connection>) {
62
- // if no change is detected, skip update. ctx is a special case
63
- if (!change.ctx && Object.entries(change).every(([k,v]) => _.isEqual(v, conn[k as keyof Connection]) ))
64
- return
62
+ if (change.op)
63
+ change.opProgress ??= change.opOffset || 0
64
Object.assign(conn, change)
65
events.emit('connectionUpdated', conn, change)
66
}
src/middlewares.ts
+2
-2
@@ -235,9 +235,9 @@ export const prepareState: Koa.Middleware = async (ctx, next) => {
235
ctx.state.account = await getHttpAccount(ctx) ?? getAccount(ctx.session?.username, false)
236
const conn = ctx.state.connection = socket2connection(ctx.socket)
237
ctx.state.revProxyPath = ctx.get('x-forwarded-prefix')
238
- await next()
238
if (conn)
240
- updateConnection(conn, { ctx })
239
+ updateConnection(conn, { ctx, op: undefined })
240
+ await next()
241
}
242
243
async function getHttpAccount(ctx: Koa.Context) {
src/serveFile.ts
+2
-1
@@ -76,7 +76,8 @@ export async function serveFile(ctx: Koa.Context, source:string, mime?:string, c
76
return ctx.body = content
77
const { size } = stats
78
const range = getRange(ctx, size)
79
- ctx.body = createReadStream(source, range)
79
+ ctx.body = createReadStream(source, range).on('end', () =>
80
+ updateConnection(ctx.state.connection, { opProgress: 1 }) )
81
if (ctx.vfsNode)
82
updateConnection(ctx.state.connection, {
83
ctx, // this will cause 'path' to be sent as well
src/throttler.ts
+1
-1
@@ -53,7 +53,7 @@ export const throttler: Koa.Middleware = async (ctx, next) => {
53
updateConnection(conn, {
54
outSpeed,
55
sent: conn.socket.bytesWritten,
56
- opProgress: (conn.opOffset || 0) + ts.getBytesSent() / conn.opTotal!,
56
+ opProgress: conn.opTotal && ((conn.opOffset || 0) + (ts.getBytesSent() - offset) / conn.opTotal),
57
})
58
/* in case this stream stands still for a while (before the end), we'll have neither 'sent' or 'close' events,
59
* so who will take care to updateConnection? This artificial next-call will ensure just that */