jaseci 1.4.2.5__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of jaseci might be problematic. Click here for more details.

Files changed (186) hide show
  1. jaseci/__init__.py +3 -37
  2. jaseci-2.0.0.dist-info/METADATA +65 -0
  3. jaseci-2.0.0.dist-info/RECORD +4 -0
  4. {jaseci-1.4.2.5.dist-info → jaseci-2.0.0.dist-info}/WHEEL +1 -2
  5. jaseci/VERSION +0 -1
  6. jaseci/cli_tools/__init__.py +0 -0
  7. jaseci/cli_tools/book_tools.py +0 -457
  8. jaseci/cli_tools/jsctl.py +0 -500
  9. jaseci/cli_tools/tests/__init__.py +0 -0
  10. jaseci/cli_tools/tests/test_jsctl.py +0 -556
  11. jaseci/extens/__init__.py +0 -0
  12. jaseci/extens/act_lib/__init__.py +0 -0
  13. jaseci/extens/act_lib/date.py +0 -117
  14. jaseci/extens/act_lib/elastic.py +0 -87
  15. jaseci/extens/act_lib/file.py +0 -76
  16. jaseci/extens/act_lib/file_handler.py +0 -189
  17. jaseci/extens/act_lib/internal.py +0 -18
  18. jaseci/extens/act_lib/jaseci.py +0 -61
  19. jaseci/extens/act_lib/mail.py +0 -10
  20. jaseci/extens/act_lib/maths.py +0 -168
  21. jaseci/extens/act_lib/net.py +0 -191
  22. jaseci/extens/act_lib/rand.py +0 -82
  23. jaseci/extens/act_lib/regex.py +0 -85
  24. jaseci/extens/act_lib/request.py +0 -169
  25. jaseci/extens/act_lib/std.py +0 -235
  26. jaseci/extens/act_lib/storage.py +0 -53
  27. jaseci/extens/act_lib/stripe.py +0 -337
  28. jaseci/extens/act_lib/task.py +0 -13
  29. jaseci/extens/act_lib/tests/__init__.py +0 -0
  30. jaseci/extens/act_lib/tests/std_test_code.py +0 -37
  31. jaseci/extens/act_lib/tests/test_date.py +0 -26
  32. jaseci/extens/act_lib/tests/test_elastic.py +0 -159
  33. jaseci/extens/act_lib/tests/test_file.py +0 -116
  34. jaseci/extens/act_lib/tests/test_file_lib.py +0 -40
  35. jaseci/extens/act_lib/tests/test_mail_lib.py +0 -33
  36. jaseci/extens/act_lib/tests/test_maths.py +0 -147
  37. jaseci/extens/act_lib/tests/test_net_lib.py +0 -62
  38. jaseci/extens/act_lib/tests/test_regex.py +0 -61
  39. jaseci/extens/act_lib/tests/test_std.py +0 -51
  40. jaseci/extens/act_lib/tests/test_std_lib.py +0 -36
  41. jaseci/extens/act_lib/tests/test_url.py +0 -32
  42. jaseci/extens/act_lib/tests/test_vector.py +0 -36
  43. jaseci/extens/act_lib/tests/test_webtool.py +0 -44
  44. jaseci/extens/act_lib/tests/test_zlib.py +0 -24
  45. jaseci/extens/act_lib/url.py +0 -79
  46. jaseci/extens/act_lib/vector.py +0 -157
  47. jaseci/extens/act_lib/webtool.py +0 -28
  48. jaseci/extens/act_lib/zip.py +0 -33
  49. jaseci/extens/api/__init__.py +0 -0
  50. jaseci/extens/api/actions_api.py +0 -170
  51. jaseci/extens/api/alias_api.py +0 -139
  52. jaseci/extens/api/architype_api.py +0 -196
  53. jaseci/extens/api/config_api.py +0 -129
  54. jaseci/extens/api/global_api.py +0 -84
  55. jaseci/extens/api/graph_api.py +0 -167
  56. jaseci/extens/api/health_api.py +0 -20
  57. jaseci/extens/api/interface.py +0 -268
  58. jaseci/extens/api/jac_api.py +0 -171
  59. jaseci/extens/api/jsorc_api.py +0 -316
  60. jaseci/extens/api/logger_api.py +0 -89
  61. jaseci/extens/api/master_api.py +0 -133
  62. jaseci/extens/api/object_api.py +0 -101
  63. jaseci/extens/api/prometheus_api.py +0 -74
  64. jaseci/extens/api/queue_api.py +0 -140
  65. jaseci/extens/api/sentinel_api.py +0 -270
  66. jaseci/extens/api/super_api.py +0 -64
  67. jaseci/extens/api/tests/__init__.py +0 -0
  68. jaseci/extens/api/tests/test_architype_api.py +0 -66
  69. jaseci/extens/api/tests/test_global_api.py +0 -179
  70. jaseci/extens/api/tests/test_graph_api.py +0 -64
  71. jaseci/extens/api/tests/test_logger_api.py +0 -43
  72. jaseci/extens/api/tests/test_object_api.py +0 -20
  73. jaseci/extens/api/tests/test_sentinel_api.py +0 -66
  74. jaseci/extens/api/tests/test_uncommon.py +0 -107
  75. jaseci/extens/api/tests/test_user_api.py +0 -32
  76. jaseci/extens/api/tests/test_walker_api.py +0 -316
  77. jaseci/extens/api/user_api.py +0 -144
  78. jaseci/extens/api/walker_api.py +0 -298
  79. jaseci/extens/api/webhook_api.py +0 -74
  80. jaseci/extens/svc/__init__.py +0 -0
  81. jaseci/extens/svc/elastic_svc.py +0 -366
  82. jaseci/extens/svc/kube_svc.py +0 -432
  83. jaseci/extens/svc/mail_svc.py +0 -156
  84. jaseci/extens/svc/prome_svc.py +0 -378
  85. jaseci/extens/svc/redis_svc.py +0 -63
  86. jaseci/extens/svc/storage_svc.py +0 -193
  87. jaseci/extens/svc/stripe_svc.py +0 -51
  88. jaseci/extens/svc/task_svc.py +0 -155
  89. jaseci/extens/svc/tasks.py +0 -302
  90. jaseci/jac/__init__.py +0 -0
  91. jaseci/jac/interpreter/__init__.py +0 -0
  92. jaseci/jac/interpreter/architype_interp.py +0 -214
  93. jaseci/jac/interpreter/interp.py +0 -1783
  94. jaseci/jac/interpreter/sentinel_interp.py +0 -257
  95. jaseci/jac/interpreter/tests/__init__.py +0 -0
  96. jaseci/jac/interpreter/tests/test_interp.py +0 -42
  97. jaseci/jac/interpreter/walker_interp.py +0 -248
  98. jaseci/jac/ir/__init__.py +0 -0
  99. jaseci/jac/ir/ast.py +0 -73
  100. jaseci/jac/ir/ast_builder.py +0 -249
  101. jaseci/jac/ir/jac_code.py +0 -152
  102. jaseci/jac/ir/passes/__init__.py +0 -6
  103. jaseci/jac/ir/passes/ast_prune_pass.py +0 -9
  104. jaseci/jac/ir/passes/codegen_pass.py +0 -244
  105. jaseci/jac/ir/passes/ir_pass.py +0 -29
  106. jaseci/jac/ir/passes/printer_pass.py +0 -23
  107. jaseci/jac/ir/passes/pt_prune_pass.py +0 -29
  108. jaseci/jac/ir/passes/schedule.py +0 -23
  109. jaseci/jac/ir/passes/stats_pass.py +0 -16
  110. jaseci/jac/jac.g4 +0 -450
  111. jaseci/jac/jac_parse/__init__.py +0 -0
  112. jaseci/jac/jac_parse/jacLexer.py +0 -809
  113. jaseci/jac/jac_parse/jacListener.py +0 -853
  114. jaseci/jac/jac_parse/jacParser.py +0 -9192
  115. jaseci/jac/jac_set.py +0 -119
  116. jaseci/jac/jsci_vm/__init__.py +0 -0
  117. jaseci/jac/jsci_vm/disasm.py +0 -94
  118. jaseci/jac/jsci_vm/inst_ptr.py +0 -31
  119. jaseci/jac/jsci_vm/machine.py +0 -188
  120. jaseci/jac/jsci_vm/op_codes.py +0 -82
  121. jaseci/jac/jsci_vm/tests/__init__.py +0 -0
  122. jaseci/jac/jsci_vm/tests/test_codegen.py +0 -31
  123. jaseci/jac/machine/__init__.py +0 -0
  124. jaseci/jac/machine/jac_scope.py +0 -85
  125. jaseci/jac/machine/jac_value.py +0 -226
  126. jaseci/jac/machine/machine_state.py +0 -383
  127. jaseci/jac/tests/__init__.py +0 -0
  128. jaseci/jac/tests/book_code.py +0 -624
  129. jaseci/jac/tests/test_book.py +0 -380
  130. jaseci/jac/tests/test_lang_14.py +0 -49
  131. jaseci/jsorc/__init__.py +0 -7
  132. jaseci/jsorc/jsorc.py +0 -642
  133. jaseci/jsorc/jsorc_settings.py +0 -211
  134. jaseci/jsorc/jsorc_utils.py +0 -298
  135. jaseci/jsorc/live_actions.py +0 -364
  136. jaseci/jsorc/manifests/__init__.py +0 -0
  137. jaseci/jsorc/manifests/database.yaml +0 -109
  138. jaseci/jsorc/manifests/elastic.yaml +0 -6024
  139. jaseci/jsorc/manifests/prometheus.yaml +0 -1383
  140. jaseci/jsorc/manifests/redis.yaml +0 -64
  141. jaseci/jsorc/memory.py +0 -258
  142. jaseci/jsorc/redis.py +0 -139
  143. jaseci/jsorc/remote_actions.py +0 -157
  144. jaseci/jsorc/tests/__init__.py +0 -0
  145. jaseci/jsorc/tests/test_actions.py +0 -542
  146. jaseci/jsorc/tests/test_jsorc.py +0 -112
  147. jaseci/prim/__init__.py +0 -0
  148. jaseci/prim/ability.py +0 -93
  149. jaseci/prim/architype.py +0 -89
  150. jaseci/prim/edge.py +0 -172
  151. jaseci/prim/element.py +0 -233
  152. jaseci/prim/graph.py +0 -26
  153. jaseci/prim/master.py +0 -64
  154. jaseci/prim/node.py +0 -532
  155. jaseci/prim/obj_mixins.py +0 -235
  156. jaseci/prim/sentinel.py +0 -281
  157. jaseci/prim/super_master.py +0 -31
  158. jaseci/prim/walker.py +0 -261
  159. jaseci/svc/__init__.py +0 -0
  160. jaseci/tests/__init__.py +0 -0
  161. jaseci/tests/infer.py +0 -39
  162. jaseci/tests/jac_test_code.py +0 -1293
  163. jaseci/tests/jac_test_progs.py +0 -774
  164. jaseci/tests/test_core.py +0 -153
  165. jaseci/tests/test_jac.py +0 -824
  166. jaseci/tests/test_node.py +0 -89
  167. jaseci/tests/test_progs.py +0 -702
  168. jaseci/tests/test_stack.py +0 -220
  169. jaseci/tests/test_stripe.py +0 -225
  170. jaseci/utils/__init__.py +0 -0
  171. jaseci/utils/actions/__init__.py +0 -0
  172. jaseci/utils/actions/actions_manager.py +0 -254
  173. jaseci/utils/actions/actions_optimizer.py +0 -516
  174. jaseci/utils/actions/actions_state.py +0 -95
  175. jaseci/utils/file_handler.py +0 -171
  176. jaseci/utils/gprof2dot.py +0 -3786
  177. jaseci/utils/id_list.py +0 -168
  178. jaseci/utils/json_handler.py +0 -70
  179. jaseci/utils/log_utils.py +0 -57
  180. jaseci/utils/test_core.py +0 -62
  181. jaseci/utils/utils.py +0 -387
  182. jaseci-1.4.2.5.dist-info/LICENSE +0 -21
  183. jaseci-1.4.2.5.dist-info/METADATA +0 -39
  184. jaseci-1.4.2.5.dist-info/RECORD +0 -184
  185. jaseci-1.4.2.5.dist-info/entry_points.txt +0 -3
  186. jaseci-1.4.2.5.dist-info/top_level.txt +0 -1
@@ -1,516 +0,0 @@
1
- """
2
- Module that manage and optimizes the actions configuration of Jaseci
3
- """
4
- from jaseci.jsorc.jsorc import JsOrc
5
- from jaseci.extens.svc.kube_svc import KubeService
6
- from jaseci.jsorc.remote_actions import ACTIONS_SPEC_LOC
7
- from jaseci.utils.utils import logger
8
- from jaseci.jsorc.live_actions import (
9
- load_module_actions,
10
- unload_module,
11
- unload_remote_actions,
12
- load_remote_actions,
13
- live_actions,
14
- action_configs,
15
- )
16
-
17
- import requests
18
- import copy
19
- import time
20
-
21
- from .actions_state import ActionsState
22
-
23
- POLICIES = ["Default", "Evaluation"]
24
- THRESHOLD = 0.2
25
- NODE_MEM_THRESHOLD = 0.8
26
-
27
-
28
- class ActionsOptimizer:
29
- def __init__(
30
- self,
31
- namespace: str = "default",
32
- policy: str = "Default",
33
- benchmark: dict = {},
34
- actions_history: dict = {},
35
- actions_calls: dict = {},
36
- ) -> None:
37
- self.actions_state = ActionsState()
38
- self.actions_change = {}
39
- self.jsorc_interval = 0
40
- self.namespace = namespace
41
- self.policy = policy
42
- self.benchmark = benchmark
43
- self.actions_history = actions_history
44
- self.actions_calls = actions_calls
45
- self.policy_params = {}
46
- self.policy_state = {}
47
- self.last_eval_configs = []
48
-
49
- def kube_create(self, config):
50
- kube = JsOrc.svc("kube").poke(cast=KubeService)
51
- for kind, conf in config.items():
52
- name = conf["metadata"]["name"]
53
- kube.create(kind, name, conf, kube.namespace, "ActionsOptimzer:")
54
-
55
- def kube_delete(self, config):
56
- kube = JsOrc.svc("kube").poke(cast=KubeService)
57
- for kind, conf in config.items():
58
- name = conf["metadata"]["name"]
59
- kube.delete(kind, name, kube.namespace, "ActionsOptimzer:")
60
-
61
- def get_actions_status(self, name=""):
62
- """
63
- Return the state of action
64
- """
65
- if name == "":
66
- return self.actions_state.get_all_state()
67
- else:
68
- return self.actions_state.get_state(name)
69
-
70
- def retire_remote(self, name):
71
- """
72
- Retire a microservice through the kube service
73
- """
74
- config = action_configs[name]["remote"]
75
- self.kube_delete(config)
76
- self.actions_state.remove_remote(name)
77
-
78
- def spawn_remote(self, name):
79
- """
80
- Spawn a microservice through the kube service
81
- """
82
- config = action_configs[name]["remote"]
83
- self.kube_create(config)
84
- url = f"http://{config['Service']['metadata']['name']}/"
85
- return url
86
-
87
- def call_action(self, action_name, *params):
88
- """
89
- Call an action via live_actions
90
- """
91
- func = live_actions[action_name]
92
- func(*params)
93
-
94
- def action_prep(self, name):
95
- """
96
- Any action preparation that needs to be called right after action is loaded
97
- """
98
- pass
99
-
100
- def load_action_remote(self, name, unload_existing=False):
101
- """
102
- Load a remote action.
103
- JSORC will get the URL of the remote microservice
104
- and stand up a microservice if there isn't currently one in the cluster.
105
- Return True if the remote action is loaded successfully,
106
- False otherwise
107
- """
108
- cur_state = self.actions_state.get_state(name)
109
- if cur_state is None:
110
- cur_state = self.actions_state.init_state(name)
111
-
112
- if cur_state["mode"] == "remote" and cur_state["remote"]["status"] == "READY":
113
- # Check if there is already a remote action loaded
114
- return True
115
-
116
- url = self.actions_state.get_remote_url(name)
117
- if url is None:
118
- # Spawn a remote microservice
119
- url = self.spawn_remote(name)
120
- self.actions_state.start_remote_service(name, url)
121
- cur_state = self.actions_state.get_state(name)
122
-
123
- if cur_state["remote"]["status"] == "STARTING":
124
- if_ready = self.remote_action_ready_check(name, url)
125
- if if_ready:
126
- self.actions_state.set_remote_action_ready(name)
127
- cur_state = self.actions_state.get_state(name)
128
-
129
- if cur_state["remote"]["status"] == "READY":
130
- if unload_existing:
131
- self.unload_action_module(name)
132
- load_remote_actions(url)
133
- self.action_prep(name)
134
- self.actions_state.remote_action_loaded(name)
135
- return True
136
-
137
- return False
138
-
139
- def load_action_module(self, name, unload_existing=False):
140
- """
141
- Load an action module
142
- """
143
- cur_state = self.actions_state.get_state(name)
144
- logger.info(cur_state)
145
- if cur_state is None:
146
- cur_state = self.actions_state.init_state(name)
147
-
148
- if cur_state["mode"] == "module":
149
- logger.info("ALREADY A MODULE LOADED")
150
- # Check if there is already a local action loaded
151
- return
152
-
153
- if name not in action_configs:
154
- return
155
-
156
- module = action_configs[name]["module"]
157
- loaded_module = action_configs[name]["loaded_module"]
158
- if unload_existing:
159
- self.unload_action_remote(name)
160
-
161
- load_module_actions(module, loaded_module)
162
- self.action_prep(name)
163
- self.actions_state.module_action_loaded(name, module, loaded_module)
164
-
165
- def unload_action_auto(self, name):
166
- """
167
- Unload an action based on how it is currently loaded
168
- """
169
- cur_state = self.actions_state.get_state(name)
170
- if cur_state is None:
171
- return False, "Action is not loaded."
172
- if cur_state["mode"] == "module":
173
- return self.unload_action_module(name)
174
- elif cur_state["mode"] == "remote":
175
- return self.unload_action_remote(name)
176
- return False, f"Unrecognized action loaded status {cur_state['mode']}"
177
-
178
- def unload_action_module(self, name):
179
- """
180
- Unload an action module
181
- """
182
- cur_state = self.actions_state.get_state(name)
183
- if cur_state is None:
184
- return False, "Action is not loaded."
185
-
186
- if cur_state["mode"] != "module":
187
- return False, "Action is not loaded as module."
188
-
189
- module_name = cur_state["module"]["name"]
190
- loaded_module = cur_state["module"]["loaded_module"]
191
-
192
- unload_module(module_name)
193
- unload_module(loaded_module)
194
- self.actions_state.module_action_unloaded(name)
195
-
196
- return (True, f"Action module {name} unloaded.")
197
-
198
- def unload_action_remote(self, name):
199
- """
200
- Unload a remote action
201
- """
202
- cur_state = self.actions_state.get_state(name)
203
- if cur_state is None:
204
- return False, "Action is not loaded."
205
-
206
- if cur_state["mode"] != "remote":
207
- return False, "Action is not loaded as remote."
208
-
209
- if cur_state["remote"]["status"] != "READY":
210
- return False, "Remote action is not ready."
211
-
212
- # Get the list of actions from the action spec of the server
213
- url = cur_state["remote"]["url"]
214
-
215
- unload_remote_actions(url)
216
- self.actions_state.remote_action_unloaded(name)
217
-
218
- return (True, f"Remote actions from {url} unloaded.")
219
-
220
- def remote_action_ready_check(self, name, url):
221
- """
222
- Check if a remote action is ready by querying the action_spec endpoint
223
- """
224
- if url is None:
225
- return False
226
- spec_url = url.rstrip("/") + ACTIONS_SPEC_LOC
227
- headers = {"content-type": "application/json"}
228
- try:
229
- res = requests.get(spec_url, headers=headers, timeout=1)
230
- except (requests.exceptions.Timeout, requests.exceptions.ConnectionError):
231
- # Remote service not ready yet
232
- return False
233
-
234
- return res.status_code == 200
235
-
236
- def set_action_policy(self, policy_name: str, policy_params: dict = {}):
237
- """
238
- Set the action optimization policy for JSORC
239
- """
240
- # TODO: manage policy switching if there are unresolved actions state
241
- if policy_name in POLICIES:
242
- self.policy = policy_name
243
- self.policy_state[policy_name] = {}
244
- self.policy_params = policy_params
245
- return True
246
- else:
247
- return f"Policy {policy_name} not found."
248
-
249
- def get_action_policy(self):
250
- """
251
- Return the currently active action policy
252
- """
253
- return self.policy
254
-
255
- def run(self, jsorc_interval: int):
256
- """
257
- The main optimization function.
258
- This gets invoked by JSROC regularly at a configured interval.
259
- """
260
- self.jsorc_interval = jsorc_interval
261
- if self.policy == "Default":
262
- # Default policy does not manage action automatically
263
- return
264
- elif self.policy == "Evaluation":
265
- self._actionpolicy_evaluation()
266
- if len(self.actions_change) > 0:
267
- self.apply_actions_change()
268
-
269
- def _init_evalution_policy(self, policy_state):
270
- # 999 is just really large memory size so everything can fits in local
271
- node_mem = self.policy_params.get("node_mem", 999 * 1024)
272
- jaseci_runtime_mem = self.policy_params.get("jaseci_runtime_mem", 300)
273
- # Initialize configs to eval
274
- actions = self.actions_state.get_active_actions()
275
- # construct list of possible configurations
276
- all_configs = [{"local_mem": jaseci_runtime_mem}]
277
- for act in actions:
278
- new_configs = []
279
- for con in all_configs:
280
- for m in ["local", "remote"]:
281
- c = copy.deepcopy(con)
282
- c[act] = m
283
- if m == "local":
284
- local_mem_requirement = action_configs[act][
285
- "local_mem_requirement"
286
- ]
287
- c["local_mem"] = c["local_mem"] + local_mem_requirement
288
- if c["local_mem"] < (node_mem * NODE_MEM_THRESHOLD):
289
- new_configs.append(dict(c))
290
- else:
291
- logger.info(
292
- f"config dropped for memory constraint: {c},\n\tcurrent node memory: {node_mem}\n\tavailable memory: {(node_mem * NODE_MEM_THRESHOLD)-c['local_mem'] }"
293
- )
294
- else:
295
- new_configs.append(dict(c))
296
- all_configs = list(new_configs)
297
- policy_state["remain_configs"] = all_configs
298
-
299
- def _actionpolicy_evaluation(self):
300
- """
301
- A evaluation based policy.
302
- JSORC cycle through possible action configurations and evaluate request performance and select the one with the best performance.
303
- Use the post_request_hook from JSORC to track request performance
304
- """
305
- logger.info("===Evaluation Policy===")
306
- policy_state = self.policy_state["Evaluation"]
307
-
308
- if len(policy_state) == 0:
309
- # Initialize policy tracking state
310
- policy_state = {
311
- "phase": "eval", # current phase of policy: eval|perf
312
- "cur_config": None, # current active configuration
313
- "remain_configs": [], # remaining configurations that need to be evaluated
314
- "past_configs": [], # configurations already evaluated
315
- "eval_phase": self.policy_params.get(
316
- "eval_phase", 10
317
- ), # how long is evaluatin period (in seconds)
318
- "perf_phase": self.policy_params.get(
319
- "perf_phase", 100
320
- ), # how long is the performance period (in seconds)
321
- "cur_phase": 0, # how long the current period has been running
322
- "prev_best_config": self.actions_state.get_all_state(),
323
- }
324
- policy_state["cur_phase"] += self.jsorc_interval
325
-
326
- # check if we should go into evaluation phase
327
- if (
328
- policy_state["phase"] == "perf"
329
- and policy_state["cur_phase"] >= policy_state["perf_phase"]
330
- ):
331
- # if no enough walker were execueted in this period, keep in perf phase
332
- if "walker_run" not in self.benchmark["requests"]:
333
- policy_state["cur_phase"] = 0
334
- else:
335
- logger.info("===Evaluation Policy=== Switching to evaluation mode")
336
- policy_state["phase"] = "eval"
337
- policy_state["cur_phase"] = 0
338
- policy_state["cur_config"] = None
339
- if len(policy_state["remain_configs"]) == 0:
340
- self._init_evalution_policy(policy_state)
341
- if policy_state["phase"] == "eval":
342
- # In evaluation phase
343
- if policy_state["cur_config"] is None:
344
- self._init_evalution_policy(policy_state)
345
-
346
- # This is the start of evaluation period
347
- policy_state["cur_config"] = policy_state["remain_configs"][0]
348
- del policy_state["remain_configs"][0]
349
- policy_state["cur_phase"] = 0
350
- self.benchmark["active"] = True
351
- self.benchmark["requests"] = {}
352
- self.actions_change = self._get_action_change(
353
- policy_state["cur_config"]
354
- )
355
- if len(self.actions_change) > 0:
356
- logger.info(
357
- f"===Evaluation Policy=== Switching eval config to {policy_state['cur_config']}"
358
- )
359
- policy_state["phase"] = "eval_switching"
360
- self.benchmark["active"] = False
361
- else:
362
- if policy_state["cur_phase"] >= policy_state["eval_phase"]:
363
- # The eval phase for the current configuration is complete
364
- # Get performance
365
- if "walker_run" not in self.benchmark["requests"]:
366
- # meaning no incoming requests during this period.
367
- # stay in this phase
368
- logger.info(f"===Evaluation Policy=== No walkers were executed")
369
- self.policy_state["Evaluation"] = policy_state
370
- return
371
-
372
- walker_runs = []
373
- for walker, times in self.benchmark["requests"][
374
- "walker_run"
375
- ].items():
376
- if walker == "_default_":
377
- continue
378
- else:
379
- walker_runs.extend(times)
380
-
381
- avg_walker_lat = sum(walker_runs) / len(walker_runs)
382
- policy_state["cur_config"]["avg_walker_lat"] = avg_walker_lat
383
- policy_state["past_configs"].append(policy_state["cur_config"])
384
- logger.info(
385
- f"===Evaluation Policy=== Complete evaluation period for {policy_state['cur_config']} latency: {avg_walker_lat}"
386
- )
387
-
388
- # check if all configs have been evaluated
389
- if len(policy_state["remain_configs"]) == 0:
390
- # best config is the one with the fastest walker latency during the evaluation period
391
- logger.info(f"===Evaluation Policy=== Evaluation phase over. ")
392
- best_config = min(
393
- policy_state["past_configs"],
394
- key=lambda x: x["avg_walker_lat"],
395
- )
396
- # Switch the system to the best config
397
- del best_config["avg_walker_lat"]
398
- self.actions_change = self._get_action_change(best_config)
399
-
400
- # ADAPTIVE: if the selected best config is the same config as the previous best one, double the performance period
401
- if all(
402
- [
403
- best_config[act]
404
- == policy_state["prev_best_config"][act]["mode"]
405
- for act in best_config.keys()
406
- if act in action_configs.keys()
407
- ]
408
- ):
409
- policy_state["perf_phase"] *= 2
410
- logger.info(
411
- f"===Evaluation Policy=== Best config is the same as previous one. Doubling performance phase to {policy_state['perf_phase']}"
412
- )
413
-
414
- policy_state["phase"] = "perf"
415
- policy_state["cur_config"] = None
416
- policy_state["past_configs"] = []
417
- policy_state["cur_phase"] = 0
418
- self.benchmark["requests"] = {}
419
- self.benchmark["active"] = True
420
- logger.info(
421
- f"===Evaluation Policy=== Evaluation phase over. Selected best config as {best_config}"
422
- )
423
- else:
424
- next_config = policy_state["remain_configs"][0]
425
- del policy_state["remain_configs"][0]
426
- self.actions_change = self._get_action_change(next_config)
427
- policy_state["cur_config"] = next_config
428
- policy_state["cur_phase"] = 0
429
- self.benchmark["requests"] = {}
430
- if len(self.actions_change) > 0:
431
- logger.info(
432
- f"===Evaluation Policy=== Switching eval config to {policy_state['cur_config']}"
433
- )
434
- policy_state["phase"] = "eval_switching"
435
- self.benchmark["active"] = False
436
- else:
437
- policy_state["phase"] = "eval"
438
- self.benchmark["active"] = True
439
- logger.info(
440
- f"===Evaluation Policy=== Switching to next config to evaluate {next_config}"
441
- )
442
- elif policy_state["phase"] == "eval_switching":
443
- # in the middle of switching between configs for evaluation
444
- if len(self.actions_change) == 0:
445
- # this means all actions change have been applied, start evaluation phase
446
- logger.info(
447
- f"===Evaluation Policy=== All actions change have been applied. Start evaluation phase."
448
- )
449
- policy_state["phase"] = "eval"
450
- policy_state["cur_phase"] = 0
451
- self.benchmark["active"] = True
452
- self.benchmark["requests"] = {}
453
- self.policy_state["Evaluation"] = policy_state
454
-
455
- def _get_action_change(self, new_action_state):
456
- """
457
- Given a new desired action state and the current action_state tracking, return the change set
458
- """
459
- change_state = {}
460
- for name, new_state in new_action_state.items():
461
- if name not in action_configs.keys():
462
- continue
463
- cur = self.actions_state.get_state(name)
464
- if cur is None:
465
- cur = self.actions_state.init_state(name)
466
- if new_state == "local":
467
- new_state = "module"
468
- if new_state != cur["mode"]:
469
- change_str = (
470
- f"{cur['mode'] if cur['mode'] is not None else ''}_to_{new_state}"
471
- )
472
- change_state[name] = change_str
473
- return change_state
474
-
475
- def apply_actions_change(self):
476
- """
477
- Apply any action configuration changes
478
- """
479
- actions_change = dict(self.actions_change)
480
- # For now, to_* and *_to_* are the same logic
481
- # But this might change down the line
482
- for name, change_type in actions_change.items():
483
- logger.info(f"==Actions Optimizer== Changing {name} {change_type}")
484
- if change_type in ["to_local", "_to_local", "_to_module", "to_module"]:
485
- # Switching from no action loaded to local
486
- self.load_action_module(name)
487
- del self.actions_change[name]
488
- elif change_type == "to_remote":
489
- loaded = self.load_action_remote(name)
490
- if loaded:
491
- del self.actions_change[name]
492
- elif change_type == "local_to_remote" or change_type == "module_to_remote":
493
- # loaded = self.load_action_remote(name, unload_existing=True)
494
- loaded = self.load_action_remote(name)
495
- if loaded:
496
- del self.actions_change[name]
497
- elif change_type == "remote_to_local" or change_type == "remote_to_module":
498
- # self.load_action_module(name, unload_existing=True)
499
- self.load_action_module(name)
500
- del self.actions_change[name]
501
-
502
- if len(actions_change) > 0 and self.actions_history["active"]:
503
- # Summarize action stats during this period and add to previous state
504
- self.summarize_action_calls()
505
- self.actions_history["history"].append(
506
- {"ts": time.time(), "actions_state": self.actions_state.get_all_state()}
507
- )
508
-
509
- def summarize_action_calls(self):
510
- actions_summary = {}
511
- for action_name, calls in self.actions_calls.items():
512
- actions_summary[action_name] = sum(calls) / len(calls)
513
- self.actions_calls.clear()
514
-
515
- if len(self.actions_history["history"]) > 0:
516
- self.actions_history["history"][-1]["actions_calls"] = actions_summary
@@ -1,95 +0,0 @@
1
- class ActionsState:
2
- """
3
- An object tracking the various states of available actions. Utilized by the ActionsOptimizer and ActionsOptimizerPolicy
4
- """
5
-
6
- def __init__(self):
7
- """
8
- Actions state format:
9
- actions_state = {
10
- "ACTION_NAME": {
11
- "mode": "local|remote",
12
- "module": {
13
- "name": MDOULE_NAME
14
- },
15
- "local": {
16
- "path": LOCAL MODULE FILE PATH
17
- },
18
- "remote": {
19
- "url": "remote_url of the action microservice",
20
- "status": "READY|STARTING|RETIRING"
21
- }
22
- }
23
- }
24
- """
25
- self.state = {}
26
-
27
- def init_state(self, name):
28
- """
29
- Initialize the data structure for the action state tracking for a specific action
30
- """
31
- self.state[name] = {
32
- "mode": None,
33
- "module": {"name": None, "loaded_module": None},
34
- "local": {"path": None},
35
- "remote": {"url": None, "status": None},
36
- }
37
-
38
- return self.state[name]
39
-
40
- def get_active_actions(self):
41
- """
42
- Return list of action modules currently used
43
- """
44
- return list(self.state.keys())
45
-
46
- def local_action_loaded(self, name):
47
- self.state[name]["mode"] = "local"
48
-
49
- def module_action_loaded(self, name, module, loaded):
50
- self.state[name]["mode"] = "module"
51
- self.state[name]["module"]["name"] = module
52
- self.state[name]["module"]["loaded_module"] = loaded
53
-
54
- def module_action_unloaded(self, name):
55
- self.state[name]["mode"] = None
56
- self.state[name]["module"]["name"] = None
57
-
58
- def remote_action_unloaded(self, name):
59
- self.state[name]["mode"] = None
60
-
61
- def remove_remote(self, name):
62
- self.state[name]["remote"] = {"url": None, "status": None}
63
-
64
- def remote_action_loaded(self, name):
65
- self.state[name]["mode"] = "remote"
66
-
67
- def start_remote_service(self, name, url):
68
- self.state[name]["remote"] = {"status": "STARTING", "url": url}
69
-
70
- def set_remote_action_ready(self, name):
71
- self.state[name]["remote"]["status"] = "READY"
72
-
73
- def stop_remote_action(self, name):
74
- self.state[name]["remote"] = {}
75
-
76
- def get_remote_url(self, name):
77
- if name not in self.state or "remote" not in self.state[name]:
78
- return None
79
- return self.state[name]["remote"].get("url", None)
80
-
81
- def get_all_state(self):
82
- ret = {}
83
- for name, state in self.state.items():
84
- ret[name] = {"mode": state["mode"]}
85
- return ret
86
-
87
- def get_state(self, name):
88
- return self.state.get(name, None)
89
-
90
- def set_url(self, name, url):
91
- if name not in self.state:
92
- self.state[name] = {}
93
- if "remote" not in self.state[name]:
94
- self.state[name]["remote"] = {}
95
- self.state[name]["remote"]["url"] = url