diff options
| author | 2023-07-21 11:46:49 +0100 | |
|---|---|---|
| committer | 2023-07-21 11:50:32 +0100 | |
| commit | 68480cee67f3eb928dadca5ca776f38119e231e7 (patch) | |
| tree | 3da3bd22c57476132a36ad4797e64efab739ff31 /src/modules | |
| parent | Allow timers to not be restarted after changing the interval. (diff) | |
Add incremental backoff to the filter/permchannels/xline_db modules.
Closes #1671.
Diffstat (limited to 'src/modules')
| -rw-r--r-- | src/modules/m_filter.cpp | 39 | ||||
| -rw-r--r-- | src/modules/m_permchannels.cpp | 29 | ||||
| -rw-r--r-- | src/modules/m_xline_db.cpp | 21 |
3 files changed, 79 insertions, 10 deletions
diff --git a/src/modules/m_filter.cpp b/src/modules/m_filter.cpp index 312bbc91a..53acb329c 100644 --- a/src/modules/m_filter.cpp +++ b/src/modules/m_filter.cpp @@ -206,6 +206,9 @@ private: bool dirty = false; std::string filterconf; Regex::Engine* factory; + unsigned long saveperiod; + unsigned long maxbackoff; + unsigned char backoff; void FreeFilters(); public: @@ -238,6 +241,7 @@ public: ModResult OnPreCommand(std::string& command, CommandBase::Params& parameters, LocalUser* user, bool validated) override; void OnUnloadModule(Module* mod) override; bool Tick() override; + bool WriteDatabase(); bool AppliesToMe(User* user, const FilterResult& filter, int flags); void ReadFilters(); static bool StringToFilterAction(const std::string& str, FilterAction& fa); @@ -645,7 +649,10 @@ void ModuleFilter::ReadConfig(ConfigStatus& status) filterconf = tag->getString("filename"); if (!filterconf.empty()) filterconf = ServerInstance->Config->Paths.PrependConfig(filterconf); - SetInterval(tag->getDuration("saveperiod", 5)); + saveperiod = tag->getDuration("saveperiod", 5); + backoff = tag->getNum<uint8_t>("backoff", 0); + maxbackoff = tag->getDuration("maxbackoff", saveperiod * 120, saveperiod); + SetInterval(saveperiod); factory = RegexEngine ? (RegexEngine.operator->()) : nullptr; @@ -934,9 +941,29 @@ void ModuleFilter::OnUnloadModule(Module* mod) bool ModuleFilter::Tick() { - if (!dirty) // No need to write. - return true; + if (dirty) + { + if (WriteDatabase()) + { + // If we were previously unable to write but now can then reset the time interval. + if (GetInterval() != saveperiod) + SetInterval(saveperiod, false); + + dirty = false; + } + else + { + // Back off a bit to avoid spamming opers. + if (backoff > 1) + SetInterval(std::min(GetInterval() * backoff, maxbackoff), false); + ServerInstance->Logs.Debug(MODNAME, "Trying again in {} seconds", GetInterval()); + } + } + return true; +}; +bool ModuleFilter::WriteDatabase() +{ if (filterconf.empty()) // Nothing to write to. { dirty = false; @@ -949,7 +976,7 @@ bool ModuleFilter::Tick() { ServerInstance->SNO.WriteToSnoMask('f', "Unable to save filters to \"{}\": {} ({})", newfilterconf, strerror(errno), errno); - return true; + return false; } stream @@ -977,7 +1004,7 @@ bool ModuleFilter::Tick() { ServerInstance->SNO.WriteToSnoMask('f', "Unable to save filters to \"{}\": {} ({})", newfilterconf, strerror(errno), errno); - return true; + return false; } stream.close(); @@ -990,7 +1017,7 @@ bool ModuleFilter::Tick() { ServerInstance->SNO.WriteToSnoMask('f', "Unable to replace old filter config \"{}\" with \"{}\": {} ({})", filterconf, newfilterconf, strerror(errno), errno); - return true; + return false; } dirty = false; diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp index 1d0c713b7..37e11fa55 100644 --- a/src/modules/m_permchannels.cpp +++ b/src/modules/m_permchannels.cpp @@ -176,10 +176,15 @@ class ModulePermanentChannels final , public Timer { +private: PermChannel p; bool dirty = false; bool loaded = false; bool save_listmodes; + unsigned long saveperiod; + unsigned long maxbackoff; + unsigned char backoff; + public: ModulePermanentChannels() @@ -195,7 +200,10 @@ public: permchannelsconf = tag->getString("filename"); save_listmodes = tag->getBool("listmodes", true); p.SetOperOnly(tag->getBool("operonly", true)); - SetInterval(tag->getDuration("saveperiod", 5)); + saveperiod = tag->getDuration("saveperiod", 5); + backoff = tag->getNum<uint8_t>("backoff", 0); + maxbackoff = tag->getDuration("maxbackoff", saveperiod * 120, saveperiod); + SetInterval(saveperiod); if (!permchannelsconf.empty()) permchannelsconf = ServerInstance->Config->Paths.PrependConfig(permchannelsconf); @@ -289,8 +297,23 @@ public: bool Tick() override { if (dirty) - WriteDatabase(p, save_listmodes); - dirty = false; + { + if (WriteDatabase(p, save_listmodes)) + { + // If we were previously unable to write but now can then reset the time interval. + if (GetInterval() != saveperiod) + SetInterval(saveperiod, false); + + dirty = false; + } + else + { + // Back off a bit to avoid spamming opers. + if (backoff > 1) + SetInterval(std::min(GetInterval() * backoff, maxbackoff), false); + ServerInstance->Logs.Debug(MODNAME, "Trying again in {} seconds", GetInterval()); + } + } return true; } diff --git a/src/modules/m_xline_db.cpp b/src/modules/m_xline_db.cpp index 7a3d6e683..aa79e1e10 100644 --- a/src/modules/m_xline_db.cpp +++ b/src/modules/m_xline_db.cpp @@ -39,6 +39,9 @@ class ModuleXLineDB final private: bool dirty; std::string xlinedbpath; + unsigned long saveperiod; + unsigned long maxbackoff; + unsigned char backoff; public: ModuleXLineDB() @@ -57,7 +60,10 @@ public: */ const auto& Conf = ServerInstance->Config->ConfValue("xlinedb"); xlinedbpath = ServerInstance->Config->Paths.PrependData(Conf->getString("filename", "xline.db", 1)); - SetInterval(Conf->getDuration("saveperiod", 5)); + saveperiod = Conf->getDuration("saveperiod", 5); + backoff = Conf->getNum<uint8_t>("backoff", 0); + maxbackoff = Conf->getDuration("maxbackoff", saveperiod * 120, saveperiod); + SetInterval(saveperiod); // Read xlines before attaching to events ReadDatabase(); @@ -91,7 +97,20 @@ public: if (dirty) { if (WriteDatabase()) + { + // If we were previously unable to write but now can then reset the time interval. + if (GetInterval() != saveperiod) + SetInterval(saveperiod, false); + dirty = false; + } + else + { + // Back off a bit to avoid spamming opers. + if (backoff > 1) + SetInterval(std::min(GetInterval() * backoff, maxbackoff), false); + ServerInstance->Logs.Debug(MODNAME, "Trying again in {} seconds", GetInterval()); + } } return true; } |
