Compare commits

..

2 commits

Author SHA1 Message Date
d378d1ce00 Merge pull request 'feat: Add exponential retry for api connection' (#8) from exp_retry into master
Reviewed-on: DGNum/stateless-uptime-kuma#8
Reviewed-by: thubrecht <tom.hubrecht@dgnum.eu>
2024-12-17 12:52:26 +01:00
sinavir
7dcf83dc4a
feat: Add exponential retry for api connection 2024-12-17 10:39:58 +01:00
5 changed files with 29 additions and 66 deletions

1
.envrc
View file

@ -1 +0,0 @@
use nix

View file

@ -1,9 +1,11 @@
import json import json
import logging import logging
import sys import sys
import time
import click import click
import click_log import click_log
import uptime_kuma_api
from uptime_kuma_api import UptimeKumaApi from uptime_kuma_api import UptimeKumaApi
from .hydratation import hydrate_http_probes from .hydratation import hydrate_http_probes
@ -14,6 +16,20 @@ logger = logging.getLogger(__name__)
click_log.basic_config() click_log.basic_config()
def get_api_with_retries(host, retries=5):
delay = 5
while True:
try:
return UptimeKumaApi(host)
except uptime_kuma_api.exceptions.UptimeKumaException:
logger.warn(f"Error while connectiong, retrying in {delay}s.")
if retries == 0:
raise
retries -= 1
time.sleep(delay)
delay *= 4
@click.group() @click.group()
def cli(): def cli():
pass pass
@ -76,7 +92,8 @@ def apply_json(
logger.debug( logger.debug(
f"Flags value:\n - scrape_http_keywords: {scrape_http_keywords}\n - no_autocreate_tags: {no_autocreate_tags}\n - keywords_fallback: {keywords_fallback}" f"Flags value:\n - scrape_http_keywords: {scrape_http_keywords}\n - no_autocreate_tags: {no_autocreate_tags}\n - keywords_fallback: {keywords_fallback}"
) )
with UptimeKumaApi(host) as api:
with get_api_with_retries(host) as api:
logging.debug("Reading json") logging.debug("Reading json")
data = json.load(file) data = json.load(file)
logging.debug("Parsing json") logging.debug("Parsing json")

View file

@ -5,8 +5,6 @@ Classes to make the needed operations to reach the specified state.
import logging import logging
import sys import sys
from requests.api import delete
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -15,7 +13,6 @@ class Manager:
self.api = api self.api = api
self.prune_unused = prune_unused self.prune_unused = prune_unused
self.target_tree = target_tree self.target_tree = target_tree
self.to_prune = []
def process(self): def process(self):
self.sync_tags() self.sync_tags()
@ -23,7 +20,6 @@ class Manager:
self.sync_monitors() self.sync_monitors()
self.sync_status_pages() self.sync_status_pages()
self.sync_settings() self.sync_settings()
self.prune()
self.save() self.save()
def save(self): def save(self):
@ -31,34 +27,25 @@ class Manager:
for i in v: for i in v:
i.save() # this method should be safe to be called in whatever order i.save() # this method should be safe to be called in whatever order
def prune(self):
for e in self.to_prune:
e.prune()
def sync_monitors(self): def sync_monitors(self):
logger.debug(f"Syncing monitors...")
old = self.api.get_monitors() old = self.api.get_monitors()
new = self.target_tree.get("monitors", []) new = self.target_tree.get("monitors", [])
self.sync(new, old, "name", Monitor) self.sync(new, old, "name")
def sync_notifications(self): def sync_notifications(self):
logger.debug(f"Syncing notifications...")
old = self.api.get_notifications() old = self.api.get_notifications()
new = self.target_tree.get("notifications", []) new = self.target_tree.get("notifications", [])
self.sync(new, old, "name", Notification) self.sync(new, old, "name")
def sync_tags(self): def sync_tags(self):
logger.debug(f"Syncing tags...")
old = self.api.get_tags() old = self.api.get_tags()
new = self.target_tree.get("tags", []) new = self.target_tree.get("tags", [])
self.sync(new, old, "name", Tag) self.sync(new, old, "name")
def sync_status_pages(self): def sync_status_pages(self):
logger.debug(f"Syncing status pages...")
old = self.api.get_status_pages() old = self.api.get_status_pages()
new = self.target_tree.get("status_pages", []) new = self.target_tree.get("status_pages", [])
self.sync(new, old, "slug", StatusPage) self.sync(new, old, "slug")
def sync_settings(self): def sync_settings(self):
if "settings" not in self.target_tree: if "settings" not in self.target_tree:
@ -71,9 +58,8 @@ class Manager:
if k not in new.kwargs: if k not in new.kwargs:
new.kwargs[k] = v new.kwargs[k] = v
def sync(self, new, old, pk, item_t): def sync(self, new, old, pk):
indexed_old = {elem[pk]: elem for elem in old} indexed_old = {elem[pk]: elem for elem in old}
indexed_new = {elem.name: elem for elem in new}
for k in new: for k in new:
if k.name in indexed_old: if k.name in indexed_old:
k.id = indexed_old[k.name]["id"] k.id = indexed_old[k.name]["id"]
@ -86,14 +72,6 @@ class Manager:
else: else:
k.id = None # Useless k.id = None # Useless
logger.debug(f"Creating key {k}") logger.debug(f"Creating key {k}")
for k in indexed_old:
if k not in indexed_new:
if item_t == StatusPage:
self.to_prune.append(item_t(api=None, name=indexed_old[k]["slug"], id=indexed_old[k]["id"]))
else:
self.to_prune.append(item_t(api=self.api, name=indexed_old[k]["name"], id=indexed_old[k]["id"]))
class Item: class Item:
@ -107,10 +85,6 @@ class Item:
def save(self): def save(self):
raise NotImplementedError() raise NotImplementedError()
def prune(self):
print(f"Would prune: {self}")
def __setattr__(self, name, value): def __setattr__(self, name, value):
if name != "saved": if name != "saved":
self.saved = False self.saved = False
@ -183,12 +157,6 @@ class Monitor(Item):
self.api.add_monitor_tag(tag_id=t.id, monitor_id=self.id, value=v) self.api.add_monitor_tag(tag_id=t.id, monitor_id=self.id, value=v)
self.saved = True self.saved = True
def prune(self):
logger.debug(f"Deleting monitor {self.name}")
self.api.delete_monitor(self.id)
def __repr__(self): def __repr__(self):
return f"Monitor({str(self)})" return f"Monitor({str(self)})"
@ -217,9 +185,6 @@ class Tag(Item):
) )
self.saved = True self.saved = True
def prune(self):
pass
def __repr__(self): def __repr__(self):
return f"Tag({str(self)})" return f"Tag({str(self)})"

View file

@ -1,17 +0,0 @@
{
"monitors": {
"mdr": {
"accepted_statuscodes": [
"200-299"
],
"headers": "{\n \"Host\": \"julienmalka.me\"\n}\n",
"keyword": "Ulm",
"type": "keyword",
"url": "https://82.67.34.230"
}
},
"notifications": {},
"settings": {},
"status_pages": {},
"tags": {}
}

View file

@ -1,7 +1,7 @@
{ {
lib, lib,
buildPythonPackage, buildPythonPackage,
fetchFromGitea, fetchFromGitHub,
setuptools, setuptools,
wheel, wheel,
packaging, packaging,
@ -11,15 +11,14 @@
buildPythonPackage rec { buildPythonPackage rec {
pname = "uptime-kuma-api"; pname = "uptime-kuma-api";
version = "2.0.0"; version = "1.2.1";
pyproject = true; pyproject = true;
src = fetchFromGitea { src = fetchFromGitHub {
domain = "git.dgnum.eu"; owner = "lucasheld";
owner = "Luj";
repo = "uptime-kuma-api"; repo = "uptime-kuma-api";
rev = "782037348df18dd32c3904c812c289f3d2d79170"; rev = version;
hash = "sha256-YK4KMtKPlxqWwzB6lLyFqLvq1RCiUWrIILcVmuiirFw="; hash = "sha256-Mgp4bSQPiEeulK9dAl+Di4Nj1HG3oVFGKr1bIdRZI44=";
}; };
nativeBuildInputs = [ nativeBuildInputs = [