您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

tasks_loop.py 10.0KB

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