refactor: Drop modules on failure
If a module error occur, just stop the failing module and let the application keep running.
This commit is contained in:
parent
69f648c513
commit
89d645539c
@ -67,6 +67,7 @@ class controller {
|
|||||||
for (auto&& block : m_modules) {
|
for (auto&& block : m_modules) {
|
||||||
for (auto&& module : block.second) {
|
for (auto&& module : block.second) {
|
||||||
module->on_update.disconnect(this, &controller::on_module_update);
|
module->on_update.disconnect(this, &controller::on_module_update);
|
||||||
|
module->on_stop.disconnect(this, &controller::on_module_stop);
|
||||||
module->stop();
|
module->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,6 +96,7 @@ class controller {
|
|||||||
for (auto&& block : m_modules) {
|
for (auto&& block : m_modules) {
|
||||||
for (auto&& module : block.second) {
|
for (auto&& module : block.second) {
|
||||||
module->on_update.disconnect(this, &controller::on_module_update);
|
module->on_update.disconnect(this, &controller::on_module_update);
|
||||||
|
module->on_stop.disconnect(this, &controller::on_module_stop);
|
||||||
module->stop();
|
module->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,7 +205,13 @@ class controller {
|
|||||||
for (auto&& block : m_modules) {
|
for (auto&& block : m_modules) {
|
||||||
for (auto&& module : block.second) {
|
for (auto&& module : block.second) {
|
||||||
module->on_update.connect(this, &controller::on_module_update);
|
module->on_update.connect(this, &controller::on_module_update);
|
||||||
module->start();
|
module->on_stop.connect(this, &controller::on_module_stop);
|
||||||
|
|
||||||
|
try {
|
||||||
|
module->start();
|
||||||
|
} catch (const application_error& err) {
|
||||||
|
m_log.err("Failed to start '%s' (reason: %s)", module->name(), err.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,6 +471,18 @@ class controller {
|
|||||||
m_bar->parse(contents);
|
m_bar->parse(contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void on_module_stop(string module_name) {
|
||||||
|
for (auto&& block : m_modules) {
|
||||||
|
for (auto&& module : block.second) {
|
||||||
|
if (module->running())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.warn("No running modules, raising SIGTERM");
|
||||||
|
kill(getpid(), SIGTERM);
|
||||||
|
}
|
||||||
|
|
||||||
void on_module_click(string input) {
|
void on_module_click(string input) {
|
||||||
if (!m_mutex.try_lock())
|
if (!m_mutex.try_lock())
|
||||||
return;
|
return;
|
||||||
|
@ -148,6 +148,7 @@ namespace modules {
|
|||||||
virtual ~module_interface() {}
|
virtual ~module_interface() {}
|
||||||
|
|
||||||
virtual string name() const = 0;
|
virtual string name() const = 0;
|
||||||
|
virtual bool running() const = 0;
|
||||||
|
|
||||||
virtual void setup() = 0;
|
virtual void setup() = 0;
|
||||||
virtual void start() = 0;
|
virtual void start() = 0;
|
||||||
@ -159,6 +160,7 @@ namespace modules {
|
|||||||
virtual bool receive_events() const = 0;
|
virtual bool receive_events() const = 0;
|
||||||
|
|
||||||
delegate::Signal1<string> on_update;
|
delegate::Signal1<string> on_update;
|
||||||
|
delegate::Signal1<string> on_stop;
|
||||||
};
|
};
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
@ -195,17 +197,23 @@ namespace modules {
|
|||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool running() const {
|
||||||
|
return enabled();
|
||||||
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
m_log.trace("%s: Setup", name());
|
m_log.trace("%s: Setup", name());
|
||||||
CAST_MODULE(Impl)->setup();
|
CAST_MODULE(Impl)->setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
// std::lock_guard<concurrency::SpinLock> lck(this->broadcast_lock);
|
if (!enabled())
|
||||||
// std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
return;
|
||||||
m_log.trace("%s: Stop", name());
|
m_log.trace("%s: Stop", name());
|
||||||
enable(false);
|
enable(false);
|
||||||
wakeup();
|
wakeup();
|
||||||
|
if (!on_stop.empty())
|
||||||
|
on_stop.emit(name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void refresh() {
|
void refresh() {
|
||||||
@ -265,8 +273,6 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string get_output() {
|
string get_output() {
|
||||||
// std::lock_guard<concurrency::SpinLock> lck(this->output_lock);
|
|
||||||
|
|
||||||
if (!enabled()) {
|
if (!enabled()) {
|
||||||
m_log.trace("%s: Module is disabled", name());
|
m_log.trace("%s: Module is disabled", name());
|
||||||
return "";
|
return "";
|
||||||
@ -332,7 +338,7 @@ namespace modules {
|
|||||||
void start() {
|
void start() {
|
||||||
CAST_MODULE(Impl)->setup();
|
CAST_MODULE(Impl)->setup();
|
||||||
CAST_MODULE(Impl)->enable(true);
|
CAST_MODULE(Impl)->enable(true);
|
||||||
CAST_MODULE(Impl)->m_threads.emplace_back(thread(&static_module::broadcast, this));
|
CAST_MODULE(Impl)->broadcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool build(builder*, string) {
|
bool build(builder*, string) {
|
||||||
@ -359,15 +365,21 @@ namespace modules {
|
|||||||
interval_t m_interval = 1s;
|
interval_t m_interval = 1s;
|
||||||
|
|
||||||
void runner() {
|
void runner() {
|
||||||
CAST_MODULE(Impl)->setup();
|
try {
|
||||||
|
CAST_MODULE(Impl)->setup();
|
||||||
|
|
||||||
while (CONST_CAST_MODULE(Impl).enabled()) {
|
while (CONST_CAST_MODULE(Impl).enabled()) {
|
||||||
{
|
{
|
||||||
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
||||||
if (CAST_MODULE(Impl)->update())
|
if (CAST_MODULE(Impl)->update())
|
||||||
CAST_MODULE(Impl)->broadcast();
|
CAST_MODULE(Impl)->broadcast();
|
||||||
|
}
|
||||||
|
CAST_MODULE(Impl)->sleep(m_interval);
|
||||||
}
|
}
|
||||||
CAST_MODULE(Impl)->sleep(m_interval);
|
} catch (const application_error& err) {
|
||||||
|
this->m_log.err("%s: %s", this->name(), err.what());
|
||||||
|
this->m_log.warn("Stopping '%s'...", this->name());
|
||||||
|
CAST_MODULE(Impl)->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -387,25 +399,31 @@ namespace modules {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void runner() {
|
void runner() {
|
||||||
CAST_MODULE(Impl)->setup();
|
try {
|
||||||
|
CAST_MODULE(Impl)->setup();
|
||||||
// warmup
|
|
||||||
CAST_MODULE(Impl)->update();
|
|
||||||
CAST_MODULE(Impl)->broadcast();
|
|
||||||
|
|
||||||
while (CONST_CAST_MODULE(Impl).enabled()) {
|
|
||||||
std::unique_lock<threading_util::spin_lock> lck(this->update_lock);
|
|
||||||
|
|
||||||
if (!CAST_MODULE(Impl)->has_event())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!CAST_MODULE(Impl)->update())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
// warmup
|
||||||
|
CAST_MODULE(Impl)->update();
|
||||||
CAST_MODULE(Impl)->broadcast();
|
CAST_MODULE(Impl)->broadcast();
|
||||||
|
|
||||||
lck.unlock();
|
while (CONST_CAST_MODULE(Impl).enabled()) {
|
||||||
CAST_MODULE(Impl)->idle();
|
std::unique_lock<threading_util::spin_lock> lck(this->update_lock);
|
||||||
|
|
||||||
|
if (!CAST_MODULE(Impl)->has_event())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!CAST_MODULE(Impl)->update())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CAST_MODULE(Impl)->broadcast();
|
||||||
|
|
||||||
|
lck.unlock();
|
||||||
|
CAST_MODULE(Impl)->idle();
|
||||||
|
}
|
||||||
|
} catch (const application_error& err) {
|
||||||
|
this->m_log.err("%s: %s", this->name(), err.what());
|
||||||
|
this->m_log.warn("Stopping '%s'...", this->name());
|
||||||
|
CAST_MODULE(Impl)->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -425,18 +443,19 @@ namespace modules {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void runner() {
|
void runner() {
|
||||||
CAST_MODULE(Impl)->setup();
|
try {
|
||||||
CAST_MODULE(Impl)->on_event(nullptr); // warmup
|
CAST_MODULE(Impl)->setup();
|
||||||
CAST_MODULE(Impl)->broadcast();
|
CAST_MODULE(Impl)->on_event(nullptr); // warmup
|
||||||
|
CAST_MODULE(Impl)->broadcast();
|
||||||
|
|
||||||
while (CAST_MODULE(Impl)->enabled()) {
|
while (CAST_MODULE(Impl)->enabled()) {
|
||||||
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
||||||
try {
|
|
||||||
CAST_MODULE(Impl)->poll_events();
|
CAST_MODULE(Impl)->poll_events();
|
||||||
} catch (const system_error& e) {
|
|
||||||
this->m_log.err("%s: Error while polling for events (what: %s)", this->name(), e.what());
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} catch (const application_error& err) {
|
||||||
|
this->m_log.err("%s: %s", this->name(), err.what());
|
||||||
|
this->m_log.warn("Stopping '%s'...", this->name());
|
||||||
|
CAST_MODULE(Impl)->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,13 +10,17 @@ namespace modules {
|
|||||||
using static_module::static_module;
|
using static_module::static_module;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
m_formatter->add(FORMAT, "", {});
|
m_formatter->add("content", "", {});
|
||||||
if (m_formatter->get(FORMAT)->value.empty())
|
|
||||||
throw undefined_format(FORMAT);
|
if (m_formatter->get("content")->value.empty())
|
||||||
|
throw module_error(name() + ".content is empty or undefined");
|
||||||
|
|
||||||
|
m_formatter->get("content")->value =
|
||||||
|
string_util::replace_all(m_formatter->get("content")->value, " ", BUILDER_SPACE_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
string get_format() {
|
string get_format() {
|
||||||
return FORMAT;
|
return "content";
|
||||||
}
|
}
|
||||||
|
|
||||||
string get_output() {
|
string get_output() {
|
||||||
@ -41,9 +45,6 @@ namespace modules {
|
|||||||
|
|
||||||
return m_builder->flush();
|
return m_builder->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
static constexpr auto FORMAT = "content";
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user