Skip to content

Instantly share code, notes, and snippets.

@lonelycode
Last active August 29, 2015 14:22
Show Gist options
  • Save lonelycode/7983389b305e55da5b27 to your computer and use it in GitHub Desktop.
Save lonelycode/7983389b305e55da5b27 to your computer and use it in GitHub Desktop.
A sample asynchronous RPC server plugin over STDIO in python for use with natefinch/pie Golang Plugin library.
#!/usr/bin/python
# Description: A sample asynchronous RPC server plugin over STDIO in python
from __future__ import print_function
import sys
import time
import pyjsonrpc
import threading
import Queue
import signal
from random import randint
queue = Queue.Queue()
def warning(*objs):
"""Handy warning log function that prints to stderr for us"""
print("[plugin log]", *objs, file=sys.stderr)
class JsonRpc(pyjsonrpc.JsonRpc):
"""
JsonRpc server example, has one method: Add(), it also adds a random sleep timer to processes
to simulate longer-running worker processes
"""
@pyjsonrpc.rpcmethod
def add(self, ints):
"""Add an array of ints together"""
v = 0
for add in ints:
v += add
time.sleep(randint(1,3))
return v
def worker(line, q, rpc_client):
"""Worker thread that handles the RPC server calls fror us when requests come in via stdin"""
out = rpc_client.call(line)
q.put(out)
return
def printer(q):
"""Output handler, printer thread will poll the results queue and output results as they appear."""
warning("Printer started")
while True:
out = q.get()
if out == "kill":
warning("Kill signal recieved, stopping threads")
return
sys.stdout.write(out + "\n")
sys.stdout.flush()
return
printer_thread = threading.Thread(target=printer, args=[queue])
def init():
"""Initialise the printer threadhm and exit signal handler so that we kill log running threads on exit"""
printer_thread.start()
def signal_handler(signal, frame):
queue.put("kill")
printer_thread.join()
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
return
def main():
rpc = JsonRpc()
line = sys.stdin.readline()
# This is a sybchronous way to poll stdin, but because we
# handle liens in threads it can handle out of order requests
while line:
try:
this_input = line
t = threading.Thread(target=worker, args=[line, queue, rpc])
t.start()
line = sys.stdin.readline()
except Exception, e:
warning("Exception occured: ", e)
queue.put("kill")
printer_thread.join()
if __name__ == "__main__":
init()
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment