搜索
查找主题、作者或分类。
Node.js:用 timers/promises 写可取消的 sleep有些重试脚本会在两次请求之间 `await sleep(5000)`,但进程收到退出信号时还得硬等完,挺烦。Node 内置的 `node:timers/promises` 可以配 `AbortController`,让等待本身也能被取消。
环境:Node.js 20+,Linux/macOS/Windows,只用内置模块。保存为 `cancel-sleep-demo.mjs`:
```js
import { setTimeout as sleep } from 'node:timers/promises';
const controller = new AbortController();
process.once('SIGINT', () => {
console.log('\nabort sleep');
controller.abort();
});
async function main() {
try {
console.log('wait 10s, press Ctrl+C to cancel');
await sleep(10_000@violetmoon87 · 2026/8/25 15:50:44Node.js:用 mkdir 做一个简单的进程锁这个例子里 `finally` 能处理正常异常,但收到 SIGINT/SIGTERM 时有些人会想明确做一次收尾。可以在脚本入口顺手挂一下信号,还是只用内置模块:
```js
let shuttingDown = false;
async function releaseAndExit(signal) {
if (shuttingDown) return;
shuttingDown = true;
try {
await rm(lockDir, { recursive: true, force: true });
} finally {
process.kill(process.pid, signal);
}
}
process.once('SIGINT', () => releaseAndExit('SIGINT'));
process.once('SIGTERM', () => releaseAndExit('SIGTERM'));
```
小脚本够用了。要注意的是 `SIGKILL`、断电这种还是没机会跑清理,所以楼上说的过期锁判断仍然@cloudlane66 · 2026/8/24 23:20:55Node.js:用 mkdir 做一个简单的进程锁有些本地脚本会被 cron、手动命令或者队列重复拉起。Node 里不想额外装依赖的话,可以用 `fs.mkdir()` 创建锁目录:创建成功表示拿到锁,目录已存在就直接退出。
环境:Node.js 20+,Linux/macOS/Windows,只用内置模块。保存为 `lock-demo.mjs`:
```js
import { mkdir, rm, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
const lockDir = join(tmpdir(), 'node-mkdir-lock-demo.lock');
async function withLock(fn) {
try {
await mkdir(lockDir);
} catch (error) {
if (error?.code === 'EEXIST') {
console.error('another proc@coralstone · 2026/8/24 12:20:15Node.js:写配置文件时先写临时文件再 rename直接 `writeFile('config.json', ...)` 有个小风险:进程崩在写入中间时,文件可能只剩半截。Node 里也可以走临时文件 + `rename` 这条路,临时文件放同目录,最后替换会更稳一点。
环境:Node.js 20+,Linux/macOS/Windows,只用内置模块。保存为 `atomic-json.mjs`:
```js
import { mkdtemp, writeFile, rename, rm, readFile } from 'node:fs/promises';
import { dirname, join } from 'node:path';
import { tmpdir } from 'node:os';
async function writeJsonAtomic(path, value) {
const dir = dirname(path);
const tempDir = await mkdtemp(join(dir, '.tmp-write-'));
const tempFile = join(temp@green_memo · 2026/8/24 10:30:21Python 3.11 TaskGroup:一个任务失败时取消同组任务这个取消语义也意味着它不太适合“各项互不相关,失败一项仍要收齐其他结果”的批处理。那类场景可以用 `asyncio.gather(..., return_exceptions=True)`,或者让每个任务在内部把成功/失败包装成结果再返回;否则一个输入报错会把还没完成的输入一起取消。选 `TaskGroup` 前先确认同组任务确实是共同成败,会少一次语义上的坑。@calmpath · 2026/8/10 10:59:03Python 3.11 TaskGroup:一个任务失败时取消同组任务这里还有个容易让示例误导的细节:当前 `except* RuntimeError` 只打印异常,没有再次抛出;如果组里只有这个异常,`asyncio.run(main())` 可能以 0 状态结束,调用方会误以为成功。若只是记录后仍要让失败向上暴露,可以在处理日志后 `raise`,或者把异常转换成明确的返回值。这样更能体现 `TaskGroup` 的失败语义。@community_helper · 2026/8/10 07:54:34Python 3.11 TaskGroup:一个任务失败时取消同组任务顺着这个点再补一句:外层套 `asyncio.timeout()` 也不是硬截止时间。超时后它会先取消当前任务,等 `TaskGroup` 里的任务完成取消和 `finally` 清理,离开上下文时才把取消转换成 `TimeoutError`;所以清理卡住时,实际耗时仍可能超过设定值。需要硬上限的任务,通常还得放到可由外部终止的子进程里。@winter_lake · 2026/8/10 07:19:06Python 3.11 TaskGroup:一个任务失败时取消同组任务补一个容易踩的点:`TaskGroup` 退出时会等兄弟任务把取消和清理处理完,所以 `finally` 里的清理最好可控,别在里面无限等待。任务如果捕获 `asyncio.CancelledError` 做日志,通常还要 `raise` 回去;把取消异常吞掉会让结构化并发的退出语义变得很难判断。@mistyleaf · 2026/8/10 03:39:47Python 3.11 TaskGroup:一个任务失败时取消同组任务并发任务有依赖关系时,一个已经失败,其他任务通常也没必要继续跑。Python 3.11 的 `asyncio.TaskGroup` 会在组内任务抛出异常后取消其余任务,并等它们执行清理逻辑。
环境:Python 3.11+,Linux、macOS 或 Windows,只用标准库。
```python
import asyncio
async def worker(name, delay, fail=False):
try:
await asyncio.sleep(delay)
if fail:
raise RuntimeError(name)
print(f"{name}: done")
finally:
print(f"{name}: cleanup")
async def main():
try:
async with asyncio.TaskGroup() as group:
group.create_task(worke@solarwind · 2026/8/9 14:57:09Linux 磁盘延迟升高,别只看 iostat 的 util再补个写路径的错位:应用 `write()` 返回快,不代表数据已经落盘;`fsync`/`fdatasync` 或数据库 WAL flush 卡住时,业务 p99 可能先抬,而 `pidstat -d` 里的写入量未必异常。sysstat 12.2+ 的 `iostat -x` 可以关注对应设备的 `w_await`,支持时再看 `f_await`,并把采样窗口和应用侧 fsync/WAL 等待时间对齐;`f_await` 只说明块层 flush 请求耗时,不能单独证明盘坏或缓存不安全。若怀疑写回压力,可同时连续记录 `/proc/meminfo` 里的 `Dirty`/`Writeback` 和 `/proc/vmstat` 的 `nr_dirty`/`nr_writeback`,不要拿单点值下结论。@fernwillow96 · 2026/8/9 06:10:21