The « asynchronuous » pubsub library « moulé à l'ancienne »

Asyncronuous : controlling the timing of operations by the use of pulses sent when the previous operation is completed rather than at regular intervals.
So it follows how to do a pubsub server in bash in less than 200 lines of code, and deploy it the overengineered way in freeBSD thinjail running on qemu in linux (for fun). I remember my Perl days when using system or the more modern Popen and procedural programming were not tabooed.

So, in nostalgia let met develop a multithreaded or multiprocessing library according to your taste. I'am really not religious on the topic, because both have the same API.

First thing to say before specialists of « orthodoxy » in python style pukes : I don't care about PEP8 and « ONE BEST WAYS ». I tend to avoid parts of python that are poorly documented like socket, hence I prefer to shamelessly « popen » a socat that transforms socket calls in processing stdin/stdout. And no, I don't say if a command succeeded because it's a « good enough » API.

Basically the API is made of 3 components :
  • pubsub that connects and authentifies
  • collect that collects all the messages (and eventually non important messages starting with "#" according to configuration) you subscribed to
  • send that sends the raw « pubsub » commands which are basically : sub channel to subscribe, pub channel content to publish on a channel
It is asynchronuous code using the timing of operation with Event (a kind of reliable signal for multiprocessing/multithreading code on python), therefore instead of putting psuedo code, I added the events relating the pseudo code...


And since I put a sample callback that mess up stdout by printing anything not on general here is a sample of how it's messy invocation looks like :
$python3  -i ./pubsub.py 
2024/05/24 16:17:29 socat[39509] W OpenSSL: Warning: this implementation does not check CRLs
>>> collect()
['# [D]:14:17:33:\x1b[0;90m\x1b[1;47m publishing in general \x1b[0m', '# [D]:14:17:34:\x1b[0;90m\x1b[1;47m subscribing <general>',
'pubsub on general at 14:17:33: new subscriber entering ']
>>> send("pub this nada")
>>> *# [I] creating <this>

>>> send("sub this")
>>> *# [D]:14:17:58: subscribing <this> 
*pubsub on this at 14:17:48: nada 

>>> send("pub this hello")
>>> *pubsub on this at 14:18:11: hello 
collect()
['# [\x1b[33mI\x1b[0m] creating <this>', 
'# [D]:14:17:58:\x1b[0;90m\x1b[1;47m subscribing <this> \x1b[0m',
'pubsub on this at 14:17:48: nada ', 
'pubsub on this at 14:18:11: hello ']
>>> 
Nothing thrilling, but, I am just always amazed at how complexity : simple pieces of less than 100 lines of codes in simple interactions with one another beats complication (huge pieces of code coupled together).

At the end, the library does not even makes 100 lines of code and you can chose your flavour of multihreading or multiprocessing and the code still works the same.

No comments: