From 143f633eaac6b762bcae7877d98fec5e2f1a994c Mon Sep 17 00:00:00 2001 From: Shyam Sunder Date: Tue, 6 Oct 2020 11:55:09 -0400 Subject: [PATCH] server/func/webhooks: call webhooks asynchronously --- server/szurubooru/func/net.py | 49 ++++++++++++++---------- server/szurubooru/tests/func/test_net.py | 17 +++----- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/server/szurubooru/func/net.py b/server/szurubooru/func/net.py index caa3fba..4e4c222 100644 --- a/server/szurubooru/func/net.py +++ b/server/szurubooru/func/net.py @@ -4,6 +4,7 @@ import os import urllib.error import urllib.request from tempfile import NamedTemporaryFile +from threading import Thread from typing import Any, Dict, List from youtube_dl import YoutubeDL @@ -63,23 +64,31 @@ def _youtube_dl_wrapper(url: str) -> bytes: ) -def post_to_webhooks(payload: Dict[str, Any]) -> List[int]: - return_list = [] - for webhook in config.config["webhooks"] or []: - req = urllib.request.Request(webhook) - req.data = json.dumps( - payload, - default=lambda x: x.isoformat("T") + "Z", - ).encode("utf-8") - req.add_header("Content-Type", "application/json") - try: - res = urllib.request.urlopen(req) - if not 200 <= res.status <= 299: - logger.warning( - f"Webhook {webhook} returned {res.status} {res.reason}" - ) - return_list.append(res.status) - except urllib.error.URLError as e: - logger.error(f"Unable to call webhook {webhook}: {str(e)}") - return_list.append(400) - return return_list +def post_to_webhooks(payload: Dict[str, Any]) -> List[Thread]: + threads = [ + Thread(target=_post_to_webhook, args=(webhook, payload)) + for webhook in (config.config["webhooks"] or []) + ] + for thread in threads: + thread.daemon = False + thread.start() + return threads + + +def _post_to_webhook(webhook: str, payload: Dict[str, Any]) -> None: + req = urllib.request.Request(webhook) + req.data = json.dumps( + payload, + default=lambda x: x.isoformat("T") + "Z", + ).encode("utf-8") + req.add_header("Content-Type", "application/json") + try: + res = urllib.request.urlopen(req) + if not 200 <= res.status <= 299: + logger.warning( + f"Webhook {webhook} returned {res.status} {res.reason}" + ) + return res.status + except urllib.error.URLError as e: + logger.warning(f"Unable to call webhook {webhook}: {str(e)}") + return 400 diff --git a/server/szurubooru/tests/func/test_net.py b/server/szurubooru/tests/func/test_net.py index af53521..65e9048 100644 --- a/server/szurubooru/tests/func/test_net.py +++ b/server/szurubooru/tests/func/test_net.py @@ -122,10 +122,8 @@ def test_no_webhooks(config_injector): ], ) def test_single_webhook(config_injector, webhook, status_code): - config_injector({"webhooks": [webhook]}) - res = net.post_to_webhooks({"test_arg": "test_value"}) - assert len(res) == 1 - assert res[0] == status_code + ret = net._post_to_webhook(webhook, {"test_arg": "test_value"}) + assert ret == status_code def test_multiple_webhooks(config_injector): @@ -133,17 +131,14 @@ def test_multiple_webhooks(config_injector): { "webhooks": [ "https://postman-echo.com/post", - "https://postman-echo.com/post", + "https://postman-echo.com/get", ] } ) - res = net.post_to_webhooks({"test_arg": "test_value"}) - assert len(res) == 2 - assert res[0] == 200 - assert res[1] == 200 + threads = net.post_to_webhooks({"test_arg": "test_value"}) + assert len(threads) == 2 def test_malformed_webhooks(config_injector): - config_injector({"webhooks": ["malformed_url"]}) with pytest.raises(ValueError): - net.post_to_webhooks({"test_arg": "test_value"}) + net._post_to_webhook("malformed_url", {"test_arg": "test_value"})