Advertisement
halcon389

uwsgidecorators.py

Aug 3rd, 2020
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.56 KB | None | 0 0
  1. from functools import partial
  2. import sys
  3. from threading import Thread
  4.  
  5. try:
  6. import cPickle as pickle
  7. except:
  8. import pickle
  9.  
  10. import uwsgi
  11.  
  12. if uwsgi.masterpid() == 0:
  13. raise Exception(
  14. "you have to enable the uWSGI master process to use this module")
  15.  
  16. spooler_functions = {}
  17. mule_functions = {}
  18. postfork_chain = []
  19.  
  20.  
  21. # Python3 compatibility
  22. def _encode1(val):
  23. if sys.version_info >= (3, 0) and isinstance(val, str):
  24. return val.encode('utf-8')
  25. else:
  26. return val
  27.  
  28.  
  29. def _decode1(val):
  30. if sys.version_info >= (3, 0) and isinstance(val, bytes):
  31. return val.decode('utf-8')
  32. else:
  33. return val
  34.  
  35.  
  36. def _encode_to_spooler(vars):
  37. return dict((_encode1(K), _encode1(V)) for (K, V) in vars.items())
  38.  
  39.  
  40. def _decode_from_spooler(vars):
  41. return dict((_decode1(K), _decode1(V)) for (K, V) in vars.items())
  42.  
  43.  
  44. def get_free_signal():
  45. for signum in range(0, 256):
  46. if not uwsgi.signal_registered(signum):
  47. return signum
  48.  
  49. raise Exception("No free uwsgi signal available")
  50.  
  51.  
  52. def manage_spool_request(vars):
  53. # To check whether 'args' is in vals or not - decode the keys first,
  54. # because in python3 all keys in 'vals' are have 'byte' types
  55. vars = dict((_decode1(K), V) for (K, V) in vars.items())
  56. if 'args' in vars:
  57. for k in ('args', 'kwargs'):
  58. vars[k] = pickle.loads(vars.pop(k))
  59.  
  60. vars = _decode_from_spooler(vars)
  61. f = spooler_functions[vars['ud_spool_func']]
  62.  
  63. if 'args' in vars:
  64. ret = f(*vars['args'], **vars['kwargs'])
  65. else:
  66. ret = f(vars)
  67.  
  68. return int(vars.get('ud_spool_ret', ret))
  69.  
  70.  
  71. def postfork_chain_hook():
  72. for f in postfork_chain:
  73. f()
  74.  
  75. uwsgi.spooler = manage_spool_request
  76. uwsgi.post_fork_hook = postfork_chain_hook
  77.  
  78.  
  79. class postfork(object):
  80. def __init__(self, f):
  81. if callable(f):
  82. self.wid = 0
  83. self.f = f
  84. else:
  85. self.f = None
  86. self.wid = f
  87. postfork_chain.append(self)
  88. def __call__(self, *args, **kwargs):
  89. if self.f:
  90. if self.wid > 0 and self.wid != uwsgi.worker_id():
  91. return
  92. return self.f()
  93. self.f = args[0]
  94.  
  95.  
  96. class _spoolraw(object):
  97.  
  98. def __call__(self, *args, **kwargs):
  99. arguments = self.base_dict.copy()
  100. if not self.pass_arguments:
  101. if len(args) > 0:
  102. arguments.update(args[0])
  103. if kwargs:
  104. arguments.update(kwargs)
  105. else:
  106. spooler_args = {}
  107. for key in ('message_dict', 'spooler', 'priority', 'at', 'body'):
  108. if key in kwargs:
  109. spooler_args.update({key: kwargs.pop(key)})
  110. arguments.update(spooler_args)
  111. arguments.update(
  112. {'args': pickle.dumps(args), 'kwargs': pickle.dumps(kwargs)})
  113. return uwsgi.spool(_encode_to_spooler(arguments))
  114.  
  115. # For backward compatibility (uWSGI < 1.9.13)
  116. def spool(self, *args, **kwargs):
  117. return self.__class__.__call__(self, *args, **kwargs)
  118.  
  119. def __init__(self, f, pass_arguments):
  120. if not 'spooler' in uwsgi.opt:
  121. raise Exception(
  122. "you have to enable the uWSGI spooler to use @%s decorator" % self.__class__.__name__)
  123. self.f = f
  124. spooler_functions[self.f.__name__] = self.f
  125. # For backward compatibility (uWSGI < 1.9.13)
  126. self.f.spool = self.__call__
  127. self.pass_arguments = pass_arguments
  128. self.base_dict = {'ud_spool_func': self.f.__name__}
  129.  
  130.  
  131. class _spool(_spoolraw):
  132.  
  133. def __call__(self, *args, **kwargs):
  134. self.base_dict['ud_spool_ret'] = str(uwsgi.SPOOL_OK)
  135. return _spoolraw.__call__(self, *args, **kwargs)
  136.  
  137.  
  138. class _spoolforever(_spoolraw):
  139.  
  140. def __call__(self, *args, **kwargs):
  141. self.base_dict['ud_spool_ret'] = str(uwsgi.SPOOL_RETRY)
  142. return _spoolraw.__call__(self, *args, **kwargs)
  143.  
  144.  
  145. def spool_decorate(f=None, pass_arguments=False, _class=_spoolraw):
  146. if not f:
  147. return partial(_class, pass_arguments=pass_arguments)
  148. return _class(f, pass_arguments)
  149.  
  150.  
  151. def spoolraw(f=None, pass_arguments=False):
  152. return spool_decorate(f, pass_arguments)
  153.  
  154.  
  155. def spool(f=None, pass_arguments=False):
  156. return spool_decorate(f, pass_arguments, _spool)
  157.  
  158.  
  159. def spoolforever(f=None, pass_arguments=False):
  160. return spool_decorate(f, pass_arguments, _spoolforever)
  161.  
  162.  
  163. class mulefunc(object):
  164.  
  165. def __init__(self, f):
  166. if callable(f):
  167. self.fname = f.__name__
  168. self.mule = 0
  169. mule_functions[f.__name__] = f
  170. else:
  171. self.mule = f
  172. self.fname = None
  173.  
  174. def real_call(self, *args, **kwargs):
  175. uwsgi.mule_msg(pickle.dumps(
  176. {
  177. 'service': 'uwsgi_mulefunc',
  178. 'func': self.fname,
  179. 'args': args,
  180. 'kwargs': kwargs
  181. }
  182. ), self.mule)
  183.  
  184. def __call__(self, *args, **kwargs):
  185. if not self.fname:
  186. self.fname = args[0].__name__
  187. mule_functions[self.fname] = args[0]
  188. return self.real_call
  189.  
  190. return self.real_call(*args, **kwargs)
  191.  
  192.  
  193. def mule_msg_dispatcher(message):
  194. msg = pickle.loads(message)
  195. if msg['service'] == 'uwsgi_mulefunc':
  196. return mule_functions[msg['func']](*msg['args'], **msg['kwargs'])
  197.  
  198. uwsgi.mule_msg_hook = mule_msg_dispatcher
  199.  
  200.  
  201. class rpc(object):
  202.  
  203. def __init__(self, name):
  204. self.name = name
  205.  
  206. def __call__(self, f):
  207. uwsgi.register_rpc(self.name, f)
  208. return f
  209.  
  210.  
  211. class farm_loop(object):
  212.  
  213. def __init__(self, f, farm):
  214. self.f = f
  215. self.farm = farm
  216.  
  217. def __call__(self):
  218. if uwsgi.mule_id() == 0:
  219. return
  220. if not uwsgi.in_farm(self.farm):
  221. return
  222. while True:
  223. message = uwsgi.farm_get_msg()
  224. if message:
  225. self.f(message)
  226.  
  227.  
  228. class farm(object):
  229.  
  230. def __init__(self, name=None, **kwargs):
  231. self.name = name
  232.  
  233. def __call__(self, f):
  234. postfork_chain.append(farm_loop(f, self.name))
  235.  
  236.  
  237. class mule_brain(object):
  238.  
  239. def __init__(self, f, num):
  240. self.f = f
  241. self.num = num
  242.  
  243. def __call__(self):
  244. if uwsgi.mule_id() == self.num:
  245. try:
  246. self.f()
  247. except:
  248. exc = sys.exc_info()
  249. sys.excepthook(exc[0], exc[1], exc[2])
  250. sys.exit(1)
  251.  
  252.  
  253. class mule_brainloop(mule_brain):
  254.  
  255. def __call__(self):
  256. if uwsgi.mule_id() == self.num:
  257. while True:
  258. try:
  259. self.f()
  260. except:
  261. exc = sys.exc_info()
  262. sys.excepthook(exc[0], exc[1], exc[2])
  263. sys.exit(1)
  264.  
  265.  
  266. class mule(object):
  267. def __init__(self, num):
  268. self.num = num
  269.  
  270. def __call__(self, f):
  271. postfork_chain.append(mule_brain(f, self.num))
  272.  
  273.  
  274. class muleloop(mule):
  275. def __call__(self, f):
  276. postfork_chain.append(mule_brainloop(f, self.num))
  277.  
  278.  
  279. class mulemsg_loop(object):
  280.  
  281. def __init__(self, f, num):
  282. self.f = f
  283. self.num = num
  284.  
  285. def __call__(self):
  286. if uwsgi.mule_id() == self.num:
  287. while True:
  288. message = uwsgi.mule_get_msg()
  289. if message:
  290. self.f(message)
  291.  
  292.  
  293. class mulemsg(object):
  294. def __init__(self, num):
  295. self.num = num
  296.  
  297. def __call__(self, f):
  298. postfork_chain.append(mulemsg_loop(f, self.num))
  299.  
  300.  
  301. class signal(object):
  302.  
  303. def __init__(self, num, **kwargs):
  304. self.num = num
  305. self.target = kwargs.get('target', '')
  306.  
  307. def __call__(self, f):
  308. uwsgi.register_signal(self.num, self.target, f)
  309. return f
  310.  
  311.  
  312. class timer(object):
  313.  
  314. def __init__(self, secs, **kwargs):
  315. self.num = kwargs.get('signum', get_free_signal())
  316. self.secs = secs
  317. self.target = kwargs.get('target', '')
  318.  
  319. def __call__(self, f):
  320. uwsgi.register_signal(self.num, self.target, f)
  321. uwsgi.add_timer(self.num, self.secs)
  322. return f
  323.  
  324.  
  325. class cron(object):
  326.  
  327. def __init__(self, minute, hour, day, month, dayweek, **kwargs):
  328. self.num = kwargs.get('signum', get_free_signal())
  329. self.minute = minute
  330. self.hour = hour
  331. self.day = day
  332. self.month = month
  333. self.dayweek = dayweek
  334. self.target = kwargs.get('target', '')
  335.  
  336. def __call__(self, f):
  337. uwsgi.register_signal(self.num, self.target, f)
  338. uwsgi.add_cron(self.num, self.minute, self.hour,
  339. self.day, self.month, self.dayweek)
  340. return f
  341.  
  342.  
  343. class rbtimer(object):
  344.  
  345. def __init__(self, secs, **kwargs):
  346. self.num = kwargs.get('signum', get_free_signal())
  347. self.secs = secs
  348. self.target = kwargs.get('target', '')
  349.  
  350. def __call__(self, f):
  351. uwsgi.register_signal(self.num, self.target, f)
  352. uwsgi.add_rb_timer(self.num, self.secs)
  353. return f
  354.  
  355.  
  356. class filemon(object):
  357.  
  358. def __init__(self, fsobj, **kwargs):
  359. self.num = kwargs.get('signum', get_free_signal())
  360. self.fsobj = fsobj
  361. self.target = kwargs.get('target', '')
  362.  
  363. def __call__(self, f):
  364. uwsgi.register_signal(self.num, self.target, f)
  365. uwsgi.add_file_monitor(self.num, self.fsobj)
  366. return f
  367.  
  368.  
  369. class erlang(object):
  370.  
  371. def __init__(self, name):
  372. self.name = name
  373.  
  374. def __call__(self, f):
  375. uwsgi.erlang_register_process(self.name, f)
  376. return f
  377.  
  378.  
  379. class lock(object):
  380. def __init__(self, f):
  381. self.f = f
  382.  
  383. def __call__(self, *args, **kwargs):
  384. # ensure the spooler will not call it
  385. if uwsgi.i_am_the_spooler():
  386. return
  387. uwsgi.lock()
  388. try:
  389. return self.f(*args, **kwargs)
  390. finally:
  391. uwsgi.unlock()
  392.  
  393.  
  394. class thread(object):
  395.  
  396. def __init__(self, f):
  397. self.f = f
  398.  
  399. def __call__(self, *args):
  400. t = Thread(target=self.f, args=args)
  401. t.daemon = True
  402. t.start()
  403. return self.f
  404.  
  405.  
  406. class harakiri(object):
  407.  
  408. def __init__(self, seconds):
  409. self.s = seconds
  410.  
  411. def real_call(self, *args, **kwargs):
  412. uwsgi.set_user_harakiri(self.s)
  413. r = self.f(*args, **kwargs)
  414. uwsgi.set_user_harakiri(0)
  415. return r
  416.  
  417. def __call__(self, f):
  418. self.f = f
  419. return self.real_call
  420.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement