Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions modules/sdk/@sfmc-sdk/src/logs/terminal-progress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ export function bindByteProgressToBar(
/* 未知→已知:重 start 以修正 total(ProgressHandle 无独立 setTotal) */
bar.start(totalMb, dlMb, { speed: speedText });
knownTotal = true;
} else {
bar.update(dlMb, { speed: speedText });
}
/* 始终 update:首帧反映已下载字节;非 TTY logger 也走统一刻度(LSP) */
bar.update(dlMb, { speed: speedText });

if (speedSampleMs <= 0 || now - lastTime >= speedSampleMs) {
lastTime = now;
Expand Down Expand Up @@ -251,8 +251,10 @@ export function createTerminalProgress(opts: TerminalProgressOptions = {}): Prog
if (!id) register();
draw();
} else if (opts.logger) {
opts.logger(`进度 0% (0/${total})`);
lastLoggedPct = 0;
/* 尊重 startValue(LSP:与 ProgressHandle.start 契约一致;重 start 修正总量时勿写死 0%) */
const pct = total > 0 ? Math.min(100, Math.round((value / total) * 100)) : 0;
opts.logger(`进度 ${pct}% (${value.toFixed(1)}/${total.toFixed(1)})`);
lastLoggedPct = Math.floor(pct / stepPercent) * stepPercent;
}
},
update(v, p) {
Expand Down
59 changes: 56 additions & 3 deletions sfmc/terminal-progress.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,33 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { Writable } from "node:stream";
import { bindByteProgressToBar, createTerminalProgress } from "@sfmc-bds/sdk/logs";
import {
bindByteProgressToBar,
createTerminalProgress,
pauseAllProgress,
resumeAllProgress,
} from "@sfmc-bds/sdk/logs";

describe("progress pause/resume contract (registry)", () => {
it("嵌套 pause 只在最外层 resume 时重绘", () => {
const stream = new Writable({
write(_chunk, _e, cb) {
cb();
},
});
const bar = createTerminalProgress({ stream, forceBar: true });
bar.start(10, 0, { speed: "0 KB/s" });

pauseAllProgress();
pauseAllProgress();
/* 嵌套 pause:内层 resume 不应重绘(pausedDepth 仍 >0) */
resumeAllProgress();
assert.equal(bar.active, true);
resumeAllProgress();
assert.equal(bar.active, true);
bar.stop();
});

it("Writable 可接收进度输出", () => {
const chunks = [];
const stream = new Writable({
Expand Down Expand Up @@ -45,6 +69,8 @@ describe("bindByteProgressToBar LSP(未知总量→已知)", () => {
onByte(512 * 1024, 0);
assert.equal(starts.length, 1);
assert.equal(starts[0].total, 1); /* 占位 1MB */
assert.equal(updates.length, 1, "首帧须 update 反映已下载字节");
assert.equal(updates[0].value, 0.5);
assert.equal(seen[0][0], 512 * 1024);
assert.equal(seen[0][1], 0);

Expand All @@ -54,24 +80,51 @@ describe("bindByteProgressToBar LSP(未知总量→已知)", () => {
assert.equal(starts.length, 2, "总量从未知变为已知时应重 start");
assert.equal(starts[1].total, 5);
assert.equal(starts[1].value, 5);
assert.equal(updates.length, 2, "重 start 后仍须 update(非 TTY logger 对齐)");
assert.equal(updates[1].value, 5);
assert.deepEqual(seen[1], [finalBytes, finalBytes]);
});

it("一开始就有 Content-Length 时不重复 start", () => {
it("一开始就有 Content-Length 时不重复 start,且首帧 update", () => {
const starts = [];
const updates = [];
const bar = {
active: true,
start(total, value = 0) {
starts.push({ total, value });
},
update() {},
update(value) {
updates.push(value);
},
stop() {},
};
const onByte = bindByteProgressToBar(bar, { speedSampleMs: 0 });
onByte(1024, 10 * 1024 * 1024);
onByte(2 * 1024 * 1024, 10 * 1024 * 1024);
assert.equal(starts.length, 1);
assert.equal(starts[0].total, 10);
assert.equal(updates.length, 2);
assert.ok(updates[0] > 0);
});

it("createTerminalProgress 非 TTY:重 start 尊重 startValue(勿写死 0%)", () => {
const logs = [];
const stream = new Writable({
write(_chunk, _e, cb) {
cb();
},
});
/* forceBar:false + logger → 非 TTY 路径 */
const bar = createTerminalProgress({
stream,
forceBar: false,
logger: (m) => logs.push(m),
});
bar.start(5, 5, { speed: "1 MB/s" });
assert.ok(logs.length >= 1);
assert.match(logs[0], /100%/);
assert.match(logs[0], /5(?:\.0)?\/5/);
bar.stop();
});

it("createTerminalProgress + binder 在 forceBar 下可跑通收尾", () => {
Expand Down