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