You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tasks_loop.py 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. import asyncio
  2. import time
  3. import redis
  4. import os
  5. import copy
  6. import json
  7. import traceback
  8. import inspect
  9. import sys
  10. import atexit
  11. from asgiref.sync import async_to_sync,sync_to_async
  12. hot_reload_build = True
  13. if not hot_reload_build:
  14. import wsps.hot_reload_temp_staging
  15. else:
  16. pass
  17. # import wsps.hot_reload_temp_staging
  18. p=print
  19. async def anop(*a,**kw):pass
  20. def nop(*a,**kw):pass
  21. class Edict(dict):pass
  22. class Eobj():pass
  23. def connect_redis1():
  24. return redis.Redis(host='localhost', port=6379, db=1,charset="utf-8", decode_responses=True, encoding_errors="backslashreplace")
  25. def connect_redis():
  26. return redis.Redis(host='localhost', port=6379, db=0,charset="utf-8", decode_responses=True, encoding_errors="backslashreplace")
  27. def eclass_factory(n):
  28. ret = []
  29. for k in range(n):
  30. class nx:pass
  31. # _rcls_name
  32. ret.append(nx)
  33. return ret
  34. def callable_helper(fn):
  35. ret = {
  36. "is_callable":0,
  37. "is_coroutine":0,
  38. }
  39. ret["is_callable"]= callable(fn)
  40. ret["is_coroutine"]= inspect.iscoroutinefunction(fn)
  41. # if (ca)
  42. return ret
  43. # verbose = print
  44. verbose=nop
  45. class DbgMixin:
  46. async def ws_rec(self,text_data,*a,**kw):
  47. # if "dbg" in
  48. text_data_json = json.loads(text_data)
  49. if not 'dbg' in text_data_json:
  50. return
  51. p("DBG!")
  52. exec(text_data_json["dbg"])
  53. class AconMixin(DbgMixin):
  54. # class AconMixin:
  55. async def connect(self):
  56. p(end="",flush=True)
  57. await self.accept()
  58. verbose("<MRO")
  59. verbose(type(self))
  60. await self.call_all_mro("ws_conn0")
  61. await self.call_all_mro("ws_conn")
  62. await self.call_all_mro("ws_conn2")
  63. verbose("/MRO>")
  64. await self.ws_conn_once()
  65. async def ws_conn_once(self, *a,**kw):pass
  66. async def ws_disconn_once(self, *a,**kw):pass
  67. async def ws_rec_once(self, *a,**kw):pass
  68. async def receive(self, *a,**kw):
  69. await self.call_all_mro("ws_rec",*a,**kw)
  70. await self.ws_rec_once(*a,**kw)
  71. print("",end="",flush=True)
  72. async def call_all_mro(self,mthd_name,*args,**kwargs):
  73. called = set([None])
  74. for cls_obj in self.__class__.__mro__:
  75. mthd = getattr(cls_obj,mthd_name,None)
  76. if not mthd in called:
  77. called.add(mthd)
  78. await mthd(self,*args,**kwargs)
  79. async def disconnect(self, close_code):
  80. await self.call_all_mro("ws_disconn",close_code)
  81. await self.ws_disconn_once(close_code)
  82. class AclTaskMixin:
  83. async def ws_disconn(self,*a,**kw):
  84. pass
  85. async def ws_conn0(self):
  86. self.groups_set = set()
  87. if glob_cl.has_cl:
  88. return
  89. glob_cl.has_cl = True
  90. glob_cl.run_persistent_loop(self)
  91. glob_cl.acl = self.channel_layer
  92. class DevMixin(*eclass_factory(10)):pass
  93. class DevMroMixin(*eclass_factory(10)):pass
  94. class WSStoMixin(*eclass_factory(10)):pass
  95. class GCLMixin(*eclass_factory(10)):pass
  96. class RldManMixin(*eclass_factory(10)):pass
  97. class LoneMixinA():pass
  98. class LoneMixinB():pass
  99. Mixins = Eobj()
  100. Mixins.DevMixin = DevMixin
  101. Mixins.DevMroMixin = DevMroMixin
  102. Mixins.WSStoMixin = WSStoMixin
  103. Mixins.GCLMixin = GCLMixin
  104. Mixins.RldManMixin = RldManMixin
  105. Mixins.LoneMixinA = LoneMixinA
  106. Mixins.LoneMixinB = LoneMixinB
  107. Mixins.DbgMixin = DbgMixin
  108. Mixins.AconMixin = AconMixin
  109. Mixins.AclTaskMixin = AclTaskMixin
  110. if not hot_reload_build:
  111. wsps.hot_reload_temp_staging.init_class_edits()
  112. class globCL(GCLMixin):
  113. def __init__(self,*a,**kw):
  114. # for now we are not going to do any weird class stuff
  115. self.acl = None
  116. self.has_cl = False
  117. self.rconn1 = connect_redis1()
  118. self.rconn = connect_redis()
  119. self.rman = RldMan()
  120. self.cbs_once = []
  121. self.cbs_asap2 = []
  122. self.cbs_asap = []
  123. self.cbs_once_set = set()
  124. if (hot_reload_build):
  125. self.cbs = {"fn1":fn1,"fn2x":nop}
  126. else:
  127. self.cbs = {}
  128. self.timeout = 1
  129. self.fast_timeout = .1
  130. pass
  131. async def persistent_fast_cb_loop_min_timeout(self,*a,**kw):
  132. while 1:
  133. if len(self.cbs_asap2):
  134. cbs_once = [*self.cbs_asap2]
  135. self.cbs_asap2=[]
  136. k=0
  137. for v in cbs_once:
  138. try:
  139. call_info = callable_helper(v)
  140. if (call_info["is_callable"]):
  141. if call_info["is_coroutine"]:
  142. pass
  143. await v({k,self})
  144. else:
  145. v({k,self})
  146. else:
  147. pass
  148. except Exception as e:
  149. p("persistent_fast_cb_loop Exception cbs_once:",e)
  150. p(flush=True)
  151. else:
  152. pass
  153. finally:
  154. pass
  155. k += 1
  156. if len(self.cbs_asap):
  157. self.cbs_asap2 = self.cbs_asap
  158. self.cbs_asap=[]
  159. await asyncio.sleep(self.fast_timeout)
  160. async def persistent_fast_cb_loop(self,*a,**kw):
  161. while 1:
  162. if len(self.cbs_asap):
  163. cbs_once = [*self.cbs_asap]
  164. self.cbs_asap=[]
  165. k=0
  166. for v in cbs_once:
  167. try:
  168. call_info = callable_helper(v)
  169. if (call_info["is_callable"]):
  170. if call_info["is_coroutine"]:
  171. pass
  172. await v({k,self})
  173. else:
  174. v({k,self})
  175. else:
  176. pass
  177. except Exception as e:
  178. p("persistent_fast_cb_loop Exception cbs_once:",e)
  179. p(flush=True)
  180. else:
  181. pass
  182. finally:
  183. pass
  184. k += 1
  185. await asyncio.sleep(self.fast_timeout)
  186. async def persistent_loop(self,*a,**kw):
  187. while 1:
  188. for k,v in [*self.cbs.items()]:
  189. try:
  190. call_info = callable_helper(v)
  191. if (call_info["is_callable"]):
  192. if call_info["is_coroutine"]:
  193. await v({k,self})
  194. else:
  195. v({k,self})
  196. else:
  197. pass
  198. pass
  199. except Exception as e:
  200. p("persistent_loop Exception",e)
  201. p(flush=True)
  202. else:
  203. pass
  204. finally:
  205. pass
  206. cbs_once = [*self.cbs_once,*self.cbs_once_set]
  207. self.cbs_once = []
  208. self.cbs_once_set = set()
  209. k=0
  210. for v in cbs_once:
  211. try:
  212. call_info = callable_helper(v)
  213. if (call_info["is_callable"]):
  214. if call_info["is_coroutine"]:
  215. pass
  216. await v({k,self})
  217. else:
  218. v({k,self})
  219. else:
  220. pass
  221. except Exception as e:
  222. p("persistent_loop Exception cbs_once:",e)
  223. p(flush=True)
  224. else:
  225. pass
  226. finally:
  227. pass
  228. k += 1
  229. await asyncio.sleep(self.timeout)
  230. def _run_persistent_loop(self,*a,**kw):
  231. p("_run_persistent_loop:")
  232. loop = asyncio.get_event_loop()
  233. self.run_persistent_loop = nop
  234. self.rman.persistent_loop_cb()
  235. loop.create_task(self.persistent_loop())
  236. # loop.create_task(self.persistent_fast_cb_loop())
  237. loop.create_task(self.persistent_fast_cb_loop_min_timeout())
  238. self.loop = loop
  239. run_persistent_loop = _run_persistent_loop
  240. def sync_dev_group_discard(self,*a,**kw):
  241. glob_cl.cbs_once.append(self.sync_dev_group_discard(*a,**kw))
  242. async def dev_group_discard(self,group_name,consumer):
  243. channel_layer = glob_cl.acl
  244. if consumer.channel_name in consumer.groups:
  245. consumer.groups.remove(group_name)
  246. await channel_layer.group_discard(group_name,consumer.channel_name)
  247. def sync_dev_group_add(self,*a,**kw):
  248. glob_cl.cbs_once.append(self.group_add(*a,**kw))
  249. async def dev_group_add(self,group_name,consumer):
  250. channel_layer = glob_cl.acl
  251. # if not consumer.channel_name in consumer.groups_set:
  252. # consumer.groups_set.add(groups)
  253. if not consumer.channel_name in consumer.groups:
  254. consumer.groups.append(group_name)
  255. await channel_layer.group_add(group_name,consumer.channel_name)
  256. # RldManMixin
  257. class RldMan(RldManMixin):
  258. def __init__(self,*a,**kw):
  259. self.files = {}
  260. z="ABC"
  261. self.scopes = {
  262. "dflt_scope":{"globals":globals(),"locals":locals()},
  263. "dflt_scope_zloc":{"globals":globals(),"locals":{}},
  264. "dflt_scope_gscope":{"globals":globals(),"locals":{}},
  265. "dflt_scope_copy": {"globals":copy.copy(globals()),"locals":copy.copy(locals())},
  266. # "dflt_scope":{"globals":globals(),"locals":{}}
  267. }
  268. self.scopes['current_scope'] = self.scopes['dflt_scope_zloc']
  269. # self.scope_opt = ""locals
  270. self.scope_opt = "globals"
  271. self.print_tb = 0
  272. base_path = "/usr/games/repos/ign4/py_rld/djc/rdir1/"
  273. file_list = [
  274. base_path+"i0.py",
  275. base_path+"i1.py",
  276. base_path+"i2.py",
  277. base_path+"i3.py",
  278. base_path+"i4.py",
  279. base_path+"i5.py",
  280. ]
  281. self.add_files(file_list)
  282. # self.add_files(file_list,{"run"})
  283. def persistent_loop_cb(self,*a,**kw):
  284. base_path = "/usr/games/repos/ign4/py_rld/djc/rdir1/"
  285. file_list = [
  286. base_path+"r0.py",
  287. base_path+"r1.py",
  288. base_path+"r2.py",
  289. base_path+"r3.py",
  290. base_path+"r4.py",
  291. base_path+"r5.py",
  292. ]
  293. self.add_files(file_list)
  294. def add_files(self,files):
  295. for file in files:
  296. if type(file)==str:
  297. self.add_file(file)
  298. elif type(file)==list:
  299. self.add_file(*file)
  300. else:
  301. p("add files???",file)
  302. def add_file(self,file_name,fnx={}):
  303. self.files[file_name] = {"ftxt":"",**fnx}
  304. def get_scope(self,rfile_obj,file_name):
  305. return self.scopes["current_scope"]
  306. return {
  307. "scope":self.scopes["current_scope"],
  308. }
  309. # rfile_obj.get("scope")
  310. # if
  311. def rld_file(self,file_name,ret= {"errs":{},"all":{},"alle":{},},**kw):
  312. if file_name in self.files:
  313. rfile_obj = self.files[file_name]
  314. st = os.stat(file_name)
  315. st_tuple = (st.st_mtime,st.st_size)
  316. # if rfile_obj["ftxt"] == "":
  317. eflag ="nd"
  318. # rfile_obj["ftxt"] = st_tuple
  319. if rfile_obj["ftxt"] != st_tuple:
  320. # p(rfile_obj["ftxt"])
  321. rfile_obj["ftxt"] = st_tuple
  322. try:
  323. f = open(file_name,"r")
  324. ftxt = f.read()
  325. # scope_key = rfile_obj.get("scope")
  326. # p(scope_key,rfile_obj)
  327. f.close()
  328. scope_obj = self.get_scope(file_name,rfile_obj)
  329. if self.scope_opt == "locals":
  330. eflag ="locals"
  331. exec(ftxt,scope_obj["globals"],scope_obj["locals"])
  332. elif self.scope_opt == "globals":
  333. eflag ="globals"
  334. exec(ftxt,scope_obj["globals"])
  335. else:
  336. eflag ="[]"
  337. exec(ftxt)
  338. except Exception as e:
  339. p()
  340. print("file:",file_name)
  341. print("EXCEPT",eflag,e)
  342. if self.print_tb:
  343. traceback.print_tb(e.__traceback__,file=sys.stdout)
  344. else:
  345. pass
  346. finally:
  347. pass
  348. print(end="",flush=True)
  349. return ret
  350. def rld_files(self):
  351. ret = {
  352. "errs":{},
  353. "all":{},
  354. "alle":{},
  355. }
  356. for k in [*self.files]:
  357. self.rld_file(k,ret)
  358. p("",end="",flush=True)
  359. return ret
  360. def fn1(*a,**kw):
  361. glob_cl.rman.rld_files()
  362. glob_cl = globCL()
  363. glob_cl.rman.rld_files()
  364. def atexit_fn():
  365. print("atexit_fn!\n\n")
  366. rconn = glob_cl.rconn
  367. # rconn.flushall()
  368. rconn.flushdb()
  369. print("",end="",flush=True)
  370. atexit.register(atexit_fn)