Be careful, starting a Python thread can introduce lag too. (if someone were to spam !postd, 100% guaranteed the server will start to lag.). My solution would be to create one thread when your plugin starts that you can pass functions to call to, like this:
Syntax: Select all
import time
import threading
import queue
from queue import Queue
from contextlib import suppress
from core import AutoUnload
from hooks.exceptions import except_hooks
from listeners import on_tick_listener_manager
from commands.say import SayCommand
from messages import SayText2
import json, urllib.request
class StoppableSPThread(threading.Thread, AutoUnload):
def __init__(self, accuracy=1, *args, **kwargs):
super().__init__(*args, **kwargs)
self.accuracy = accuracy
on_tick_listener_manager.register_listener(self._tick) # Automatically wake up every tick
self._stop = threading.Event()
def run(self):
while not self.stopped:
try:
self.do()
except Exception:
except_hooks.print_exception()
time.sleep(self.accuracy)
def do(self):
raise NotImplementedError("Override me!")
def _tick(self):
pass
def stop(self):
self._stop.set()
on_tick_listener_manager.unregister_listener(self._tick)
@property
def stopped(self):
return self._stop.is_set()
_unload_instance = stop
class ThreadedCaller(StoppableSPThread):
def __init__(self, *args, **kwargs):
self.queue = Queue()
super().__init__(*args, **kwargs)
def do(self):
with suppress(queue.Empty):
to_call = self.queue.get(block=True, timeout=10)
to_call["func"](*to_call["args"], **to_call["kwargs"])
threaded_caller = ThreadedCaller()
threaded_caller.start()
def post_request(data):
url = "https://example.com"
req = urllib.request.Request(url)
req.add_header("Content-Type", "application/json; charset=utf-8")
jsondata = json.dumps(data)
jsondataasbytes = jsondata.encode("utf-8")
req.add_header("Content-Length", len(jsondataasbytes))
print(jsondataasbytes)
response = urllib.request.urlopen(req, jsondataasbytes)
@SayCommand("!postd")
def on_say_post(command, index, team):
whatever = {"string": command.arg_string}
SayText2(whatever["string"]).send(index)
threaded_caller.queue.put_nowait({"func:":post_request, "args":(whatever,), "kwargs":{}})
(Not all of it is tested so it may have some typos.)
Btw, imo it may be a good idea to implement a worker like this in the SP library.