Made socket server more ambiguous and added prefix version
This commit is contained in:
parent
52489a4ac9
commit
ec16929aad
|
@ -73,7 +73,7 @@ class ThreadPool:
|
||||||
try:
|
try:
|
||||||
method(*args, **kwargs)
|
method(*args, **kwargs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
eprint(e)
|
||||||
finally:
|
finally:
|
||||||
# print(f"[worker:{worker_id}]: Task complete")
|
# print(f"[worker:{worker_id}]: Task complete")
|
||||||
self._exec_controls(controls)
|
self._exec_controls(controls)
|
||||||
|
|
|
@ -4,5 +4,5 @@ from abots.helpers.numbers import clamp, randfloat, isnumeric
|
||||||
from abots.helpers.general import eprint, deduce, noop, cast, get_digit, obtain
|
from abots.helpers.general import eprint, deduce, noop, cast, get_digit, obtain
|
||||||
from abots.helpers.general import utc_now, utc_now_timestamp
|
from abots.helpers.general import utc_now, utc_now_timestamp
|
||||||
from abots.helpers.logging import Logger
|
from abots.helpers.logging import Logger
|
||||||
from abots.helpers.black_magic import infinitedict, debugger
|
from abots.helpers.black_magic import infinitedict, debugger, singleton, curry
|
||||||
from abots.helpers.black_magic import coroutine, generator
|
from abots.helpers.black_magic import coroutine, generator
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
from abots.events import CoroEvent
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
@ -14,8 +13,8 @@ def debugger(func):
|
||||||
signature = ", ".join(args_repr + kwargs_repr)
|
signature = ", ".join(args_repr + kwargs_repr)
|
||||||
print(f"[DEBUGGER]: Calling {func.__name__}({signature})")
|
print(f"[DEBUGGER]: Calling {func.__name__}({signature})")
|
||||||
result = func(*args, **kwargs)
|
result = func(*args, **kwargs)
|
||||||
print(f"[DEBUGGER]: {func.__name__!r} returned {value!r}")
|
print(f"[DEBUGGER]: {func.__name__!r} returned {result!r}")
|
||||||
return value
|
return result
|
||||||
return wrapper_debug
|
return wrapper_debug
|
||||||
|
|
||||||
def coroutine(func):
|
def coroutine(func):
|
||||||
|
@ -28,13 +27,31 @@ def coroutine(func):
|
||||||
|
|
||||||
def generator(func):
|
def generator(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
@coroutine
|
|
||||||
def wrapper_generator(*args, **kwargs):
|
def wrapper_generator(*args, **kwargs):
|
||||||
event = CoroEvent()
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
yield from func(event, *args, **kwargs)
|
yield from func(*args, **kwargs)
|
||||||
except GeneratorExit:
|
except GeneratorExit:
|
||||||
pass
|
pass
|
||||||
return wrapper_generator
|
return coroutine(wrapper_generator)
|
||||||
|
|
||||||
|
def singleton(cls):
|
||||||
|
@wraps(cls)
|
||||||
|
def wrapper_singleton(*args, **kwargs):
|
||||||
|
if not wrapper_singleton.instance:
|
||||||
|
wrapper_singleton.instance = cls(*args, **kwargs)
|
||||||
|
return wrapper_singleton.instance
|
||||||
|
wrapper_singleton.instance = None
|
||||||
|
return wrapper_singleton
|
||||||
|
|
||||||
|
def curry(func, argc=None):
|
||||||
|
if argc is None:
|
||||||
|
argc = func.func_code.co_argcount
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper_curry(*args):
|
||||||
|
if len(args) == argc:
|
||||||
|
return func(*args)
|
||||||
|
def curried(*c_args):
|
||||||
|
return func(*(args + c_args))
|
||||||
|
return curry(curried, argc - len(args))
|
||||||
|
return wrapper_curry
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
"""
|
||||||
|
|
||||||
|
net/PrefixSocketServer
|
||||||
|
================
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
* Add logging to broken pipe exceptions
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from abots.net import SocketServer
|
||||||
|
|
||||||
|
class PrefixSocketServer(SocketServer):
|
||||||
|
def __init__(self, host, port, listeners=5, buffer_size=4096,
|
||||||
|
secure=False, timeout=None, daemon=False):
|
||||||
|
args = host, port, listeners, buffer_size, secure, timeout, daemon
|
||||||
|
super().__init__(*args)
|
||||||
|
|
||||||
|
def _package_message(self, message, *args):
|
||||||
|
if len(args) > 0:
|
||||||
|
formatted = message.format(*args)
|
||||||
|
else:
|
||||||
|
formatted = message
|
||||||
|
packaged = pack(">I", len(formatted)) + formatted.encode()
|
||||||
|
return packaged
|
||||||
|
|
||||||
|
# Packages a message and sends it to socket
|
||||||
|
def send_message(self, uuid, message, *args):
|
||||||
|
sock = self._sock_from_uuid(uuid)
|
||||||
|
if sock is None:
|
||||||
|
return None
|
||||||
|
formatted = self._package_message(message)
|
||||||
|
try:
|
||||||
|
sock.send(formatted)
|
||||||
|
# The socket can either be broken or no longer open at all
|
||||||
|
except (BrokenPipeError, OSError) as e:
|
||||||
|
return
|
|
@ -149,13 +149,18 @@ class SocketClient(Thread):
|
||||||
def recv(self):
|
def recv(self):
|
||||||
yield from self._obtain("outbox")
|
yield from self._obtain("outbox")
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
for letter in self.recv():
|
||||||
|
if letter is not None and len(letter) > 0:
|
||||||
|
print(letter)
|
||||||
|
|
||||||
def send(self, message):
|
def send(self, message):
|
||||||
self._inbox.put(message)
|
self._inbox.put(message)
|
||||||
cast(self._bridge, "send", ("inbox", message))
|
cast(self._bridge, "send", ("inbox", message))
|
||||||
|
|
||||||
def connect(self, bridge):
|
def connect(self, bridge):
|
||||||
self._bridge = bridge()
|
self._bridge = bridge()
|
||||||
|
|
||||||
@coroutine
|
@coroutine
|
||||||
def bridge(self, inbox, outbox, events):
|
def bridge(self, inbox, outbox, events):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -56,7 +56,7 @@ class SocketServer(Thread):
|
||||||
if self.secure:
|
if self.secure:
|
||||||
# Note: kwargs is used here to specify any SSL parameters desired
|
# Note: kwargs is used here to specify any SSL parameters desired
|
||||||
self.sock = wrap_socket(self.sock, **kwargs)
|
self.sock = wrap_socket(self.sock, **kwargs)
|
||||||
|
|
||||||
# List of all sockets involved (both client and server)
|
# List of all sockets involved (both client and server)
|
||||||
self.sockets = list()
|
self.sockets = list()
|
||||||
self.clients = list()
|
self.clients = list()
|
||||||
|
@ -151,14 +151,6 @@ class SocketServer(Thread):
|
||||||
def _sock_from_uuid(self, uuid):
|
def _sock_from_uuid(self, uuid):
|
||||||
return self.uuids.get(uuid, dict()).get("sock", None)
|
return self.uuids.get(uuid, dict()).get("sock", None)
|
||||||
|
|
||||||
def _package_message(self, message, *args):
|
|
||||||
if len(args) > 0:
|
|
||||||
formatted = message.format(*args)
|
|
||||||
else:
|
|
||||||
formatted = message
|
|
||||||
packaged = pack(">I", len(formatted)) + formatted.encode()
|
|
||||||
return packaged
|
|
||||||
|
|
||||||
# Closes a connected socket and removes it from the sockets list
|
# Closes a connected socket and removes it from the sockets list
|
||||||
def close_sock(self, uuid):
|
def close_sock(self, uuid):
|
||||||
event = dict()
|
event = dict()
|
||||||
|
@ -217,9 +209,8 @@ class SocketServer(Thread):
|
||||||
sock = self._sock_from_uuid(uuid)
|
sock = self._sock_from_uuid(uuid)
|
||||||
if sock is None:
|
if sock is None:
|
||||||
return None
|
return None
|
||||||
formatted = self._package_message(message)
|
|
||||||
try:
|
try:
|
||||||
sock.send(formatted)
|
sock.send(message)
|
||||||
# The socket can either be broken or no longer open at all
|
# The socket can either be broken or no longer open at all
|
||||||
except (BrokenPipeError, OSError) as e:
|
except (BrokenPipeError, OSError) as e:
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,14 +1,57 @@
|
||||||
#!env/bin/python3
|
#!env/bin/python3
|
||||||
|
|
||||||
from abots.net import SocketServer, SocketClient
|
#from abots.net import SocketServer, SocketClient
|
||||||
|
#
|
||||||
|
#host = "localhost"
|
||||||
|
#port = 10401
|
||||||
|
#timeout = 3
|
||||||
|
#
|
||||||
|
#server = SocketServer(host, port, timeout=timeout)
|
||||||
|
#client = SocketClient(host, port, timeout=timeout)
|
||||||
|
#
|
||||||
|
#server.start()
|
||||||
|
#server.ready.wait()
|
||||||
|
#client.start()
|
||||||
|
from abots.events import ThreadMarshal
|
||||||
|
from abots.helpers import generator
|
||||||
|
from queue import Queue, Empty
|
||||||
|
from threading import Thread, Event
|
||||||
|
|
||||||
host = "localhost"
|
def worker(queue, event, timeout):
|
||||||
port = 10401
|
while not event.is_set():
|
||||||
timeout = 3
|
try:
|
||||||
|
job = queue.get(timeout=timeout)
|
||||||
|
except Empty:
|
||||||
|
continue
|
||||||
|
assert len(job) == 2, "Expected two parameters"
|
||||||
|
done, task = job
|
||||||
|
assert hasattr(done, "set"), "Expected event"
|
||||||
|
assert len(task) == 3, "Expected three parameters"
|
||||||
|
method, args, kwargs = task
|
||||||
|
assert callable(method), "Expected function"
|
||||||
|
assert isinstance(args, tuple), "Expected tuple"
|
||||||
|
assert isinstance(kwargs, dict), "Expected dict"
|
||||||
|
try:
|
||||||
|
result = method(*args, **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
done.set()
|
||||||
|
queue.task_done()
|
||||||
|
|
||||||
server = SocketServer(host, port, timeout=timeout)
|
def manager(queue, event, timeout):
|
||||||
client = SocketClient(host, port, timeout=timeout)
|
workers = list()
|
||||||
|
current = 0
|
||||||
|
while not event.is_set():
|
||||||
|
try:
|
||||||
|
task = queue.get(timeout=timeout)
|
||||||
|
except Empty:
|
||||||
|
continue
|
||||||
|
assert len(task) == 2, "Expected two parameters"
|
||||||
|
action, payload = task
|
||||||
|
assert isinstance(action, str), "Expected str"
|
||||||
|
if action == "new":
|
||||||
|
assert callable(payload), "Expected function"
|
||||||
|
workers.append((payload))
|
||||||
|
elif action == "reserve" and len(workers) > 0:
|
||||||
|
worker = workers[current]
|
||||||
|
|
||||||
server.start()
|
|
||||||
server.ready.wait()
|
|
||||||
client.start()
|
|
Loading…
Reference in New Issue