- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
假设我有以下场景 -
async.series(
[
function (cbi) {
students.getAll('student', function (err, response) {
if (err) {
logger.error(err);
}
cbi(err, response);
});
},
function (cbi) {
students.deleteAll('student', function (err, response) {
if (err) {
logger.error(err);
}
cbi(err, response);
});
},
function (cbi) {
teachers.getAll('teacher', function (err, response) {
if (err) {
logger.error(err);
}
cbi(err, response);
});
},
function (cbi) {
teachers.deleteAll('teacher', function (err, response) {
if (err) {
logger.error(err);
}
cbi(err, response);
});
};
]
);
我希望在发送 SIGTERM
时进行优雅的清理。这是对所有学生或所有教师的清理,无论哪个正在进行,当信号发送时应该完成并且下一个不应该开始。
function (cbi) {
students.getAll('student', function (err, response) {
if (err || GLOBAL_VAR_SIGTERM === true) {
logger.error(err);
}
cbi(err, response);
});
}
我在想我应该设置一个全局变量来跟踪 SIGTERM
信号。
process.on('SIGTERM', function onSigterm () {
GLOBAL_VAR_SIGTERM = true;
}
有没有更好的方法来打破异步系列来打破 SIGTERM
信号?
最佳答案
正如@adamrights 在 his answer 中指出的那样,代码中的主要问题是您没有使用真实的 err
第一个参数调用 cbi(err, response)
,这对于停止 async 至关重要。 series
继续队列中的下一个任务。
现在您的代码应该可以工作了,但是您的代码中有一个重复模式:
function (cbi) {
students.getAll('student', function (err, response) {
// these 3 lines appear in every callback function
if (GLOBAL_VAR_SIGTERM) err = new Error("SIGTERM: Aborting remaining tasks");
if (err) logger.error(err);
cbi(err, response);
// end of repeat pattern
});
}
传递给每个异步任务的回调总是做同样的三行事情。我们知道 DRY 规则,将重复模式提取到另一个函数中以尽可能重用它总是一个好主意。
因此,与其重复声明匿名函数,不如声明一个工厂函数。
function callbackFactory(cbi) {
return function(err, response) {
if (GLOBAL_VAR_SIGTERM) err = new Error("SIGTERM: Aborting remaining tasks");
if (err) logger.error(err);
cbi(err, response);
}
}
// use arrow function to write more concise code
async.series(
[
cbi => students.getAll('student', callbackFactory(cbi)),
cbi => students.deleteAll('student', callbackFactory(cbi)),
cbi => teachers.getAll('teacher', callbackFactory(cbi)),
cbi => teachers.deleteAll('teacher', callbackFactory(cbi)),
]
);
让我们进一步探讨这个话题。显然,在收到 SIGTERM
时尽早中止是一个横切关注点,应该与业务逻辑分开。假设您的业务逻辑因任务而异:
async.series(
[
cbi => students.getAll('student', (err, response) => {
if (err) {
logger.error(err);
return cbi(err);
}
updateStudentCount(response.data.length) // <- extra work
cbi(err, response);
}),
cbi => teachers.getAll('student', (err, response) => {
if (err) {
logger.error(err);
return cbi(err);
}
updateTeacherCount(response.data.length) // <- different extra work
cbi(err, response);
})
]
);
因为回调是变化的,所以很难像以前那样提取到工厂函数中。从这个 Angular 来说,我们最好注入(inject)每个任务的abort-early行为,方便编写正常的业务逻辑。
这就是装饰器模式派上用场的地方。但是全局变量并不是实现它的最佳工具,我们将使用事件监听器。
装饰器的基本界面如下:
// `task` will be things like `cbi => students.getAll('student', ... )`
function decorateTaskAbortEarly(task) {
return (originalCbi) => {
...
task(originalCbi)
}
}
以下是我们的实现 list :
SIGTERM
,我们将调用 originalCbi
SIGTERM
时,originalCbi
仍然可以像正常情况一样在任何异步任务的回调中调用originalCbi
被调用一次,我们应该取消订阅 SIGTERM
以防止内存泄漏实现:
function decorateTaskAbortEarly(task) {
return (originalCbi) => {
// subscribe to `SIGTERM`
var listener = () => originalCbi(new Error("SIGTERM: Aborting remaining tasks"));
process.once('SIGTERM', listener);
var wrappedCbi = (err, response) => {
// unsubscribe if `cbi` is called once
process.off('SIGTERM', listener);
return originalCbi(err, response);
};
// pass `cbi` through to `task`
task(wrappedCbi);
}
}
// Usage:
async.series(
[
cbi => students.getAll('student', (err, response) => {
if (err) {
logger.error(err);
return cbi(err);
}
updateStudentCount(response.data.length)
cbi(err, response);
}),
cbi => teachers.getAll('student', (err, response) => {
if (err) {
logger.error(err);
return cbi(err);
}
updateTeacherCount(response.data.length)
cbi(err, response);
})
].map(decorateTaskAbortEarly) // <--- nice API
);
关于javascript - 如何打破 SIGTERM 上的异步系列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55776670/
当前在我的 Windows 机器上使用 Codeception 运行 PHPUnit 时出现错误: [PHPUnit_Framework_Exception] Use of undefined con
当我的 Dockerfile 以 结尾时 CMD node . docker 使用命令 /bin/sh -c "node ." 运行该容器而不是简单的 node . (我知道,我可以用 CMD ["n
在Airflow v2.6.3上,我每天运行Spark作业。每隔一段时间,DAG中的成功作业都会通过EMR传感器重试该作业。重试的作业将显示“此实例的状态已在外部设置为up_for_retry。正在终
$ cat SIGTERM #!/bin/bash set -eu flag_file=$(xdg-user-dir DESKTOP)/SIGTERM-TRAPPED trap 'touch "$fl
我有一个单线程进程,它不会因 kill -TERM 而死亡。过程 信号掩码不显示 SIGTERM 被阻止。我正在执行“杀死” 根。我可以使用 SIGKILL 终止进程,但这是更大范围的一部分 系统,我
我有一个 bash 脚本调用 run.sh启动多个进程 #!/bin/bash proc1 & proc2 & proc3 & final # this runs until sigterm 当我执行
我正在摆弄多处理和信号。我正在创建一个池,并让工作人员捕获 SIGTERM。没有明显的原因,我观察到子进程随机接收 SIGTERM 。这是一个 MWE: import multiprocessing
Java 有没有办法处理接收到的 SIGTERM? 我正在运行一个 java 服务,但不想在用户注销时关闭我的 java 服务。 只想覆盖 sigterm 关闭处理程序,但保留其余信号的处理程序。 d
操作系统 (Linux) 可以向进程发送 SIGTERM 吗?如果是,什么时候?在什么情况下?例如,当我的进程写入不正确的地址内存时,操作系统会向它发送 SIGSEGV。提前致谢 最佳答案 Can O
我正在 try catch SIGTERM 信号并在来自 Linux 守护进程的处理程序中打印一条消息: void SigStop_Handler(int sig) { D(printf("**
我有一个简单的守护进程可以归结为 #include #include #include #include #include #include bool running = true; st
Java中有没有办法处理收到的SIGTERM? 我正在运行 java 服务,但不想在用户注销时关闭我的 java 服务。 只想覆盖 sigterm 关闭处理程序,但保留其余信号的处理程序。 detai
我有一个通过响应信号来运行的 C 程序。一些信号导致父进程 fork 。这允许在父级继续响应信号的同时进行其他处理。 当父级收到 SIGTERM 时,我希望 fork 的子级也收到 SIGTERM。在
我正在做这样的事情 def exitHandler(self, *args): self.stopThreads() sys.exit(2) 然后我在我的 self.run 中注册了该
我用c设计了一个消息传递接口(interface),用于在我的系统中运行的不同进程之间提供通信。该接口(interface)为此目的创建 10-12 个线程,并使用 TCP 套接字提供通信。 它工作正
我有一个可以启动和关闭进程的类。但似乎并没有关闭该进程。 我的python代码,还有其他方法,但它们工作得很好。: class KismetInstance: """Creates a kis
我的守护进程(仅限 Linux)具有以下信号处理程序: static void signal_handler(int id, siginfo_t *si, void *context) { i
有一个守护进程有两个线程:th1,th2。 th2 使用 read(2) 读取套接字。 如果我用 SIGTERM 终止守护进程,th1 会捕获并处理信号(设置终止标志),在调用守护进程析构函数之后,它
我的程序如下: #include #include #include #include int main() { struct sigaction new_sa; struct
如果 Python 接收到 SIGTERM 但没有为其注册信号处理程序,默认情况下会在幕后做什么? 最佳答案 基于 Thomas Wouters 的回答,python 没有为 SIGTERM 信号注册
我是一名优秀的程序员,十分优秀!