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.
- jaseci/__init__.py +3 -37
- jaseci-2.0.0.dist-info/METADATA +65 -0
- jaseci-2.0.0.dist-info/RECORD +4 -0
- {jaseci-1.4.2.5.dist-info → jaseci-2.0.0.dist-info}/WHEEL +1 -2
- jaseci/VERSION +0 -1
- jaseci/cli_tools/__init__.py +0 -0
- jaseci/cli_tools/book_tools.py +0 -457
- jaseci/cli_tools/jsctl.py +0 -500
- jaseci/cli_tools/tests/__init__.py +0 -0
- jaseci/cli_tools/tests/test_jsctl.py +0 -556
- jaseci/extens/__init__.py +0 -0
- jaseci/extens/act_lib/__init__.py +0 -0
- jaseci/extens/act_lib/date.py +0 -117
- jaseci/extens/act_lib/elastic.py +0 -87
- jaseci/extens/act_lib/file.py +0 -76
- jaseci/extens/act_lib/file_handler.py +0 -189
- jaseci/extens/act_lib/internal.py +0 -18
- jaseci/extens/act_lib/jaseci.py +0 -61
- jaseci/extens/act_lib/mail.py +0 -10
- jaseci/extens/act_lib/maths.py +0 -168
- jaseci/extens/act_lib/net.py +0 -191
- jaseci/extens/act_lib/rand.py +0 -82
- jaseci/extens/act_lib/regex.py +0 -85
- jaseci/extens/act_lib/request.py +0 -169
- jaseci/extens/act_lib/std.py +0 -235
- jaseci/extens/act_lib/storage.py +0 -53
- jaseci/extens/act_lib/stripe.py +0 -337
- jaseci/extens/act_lib/task.py +0 -13
- jaseci/extens/act_lib/tests/__init__.py +0 -0
- jaseci/extens/act_lib/tests/std_test_code.py +0 -37
- jaseci/extens/act_lib/tests/test_date.py +0 -26
- jaseci/extens/act_lib/tests/test_elastic.py +0 -159
- jaseci/extens/act_lib/tests/test_file.py +0 -116
- jaseci/extens/act_lib/tests/test_file_lib.py +0 -40
- jaseci/extens/act_lib/tests/test_mail_lib.py +0 -33
- jaseci/extens/act_lib/tests/test_maths.py +0 -147
- jaseci/extens/act_lib/tests/test_net_lib.py +0 -62
- jaseci/extens/act_lib/tests/test_regex.py +0 -61
- jaseci/extens/act_lib/tests/test_std.py +0 -51
- jaseci/extens/act_lib/tests/test_std_lib.py +0 -36
- jaseci/extens/act_lib/tests/test_url.py +0 -32
- jaseci/extens/act_lib/tests/test_vector.py +0 -36
- jaseci/extens/act_lib/tests/test_webtool.py +0 -44
- jaseci/extens/act_lib/tests/test_zlib.py +0 -24
- jaseci/extens/act_lib/url.py +0 -79
- jaseci/extens/act_lib/vector.py +0 -157
- jaseci/extens/act_lib/webtool.py +0 -28
- jaseci/extens/act_lib/zip.py +0 -33
- jaseci/extens/api/__init__.py +0 -0
- jaseci/extens/api/actions_api.py +0 -170
- jaseci/extens/api/alias_api.py +0 -139
- jaseci/extens/api/architype_api.py +0 -196
- jaseci/extens/api/config_api.py +0 -129
- jaseci/extens/api/global_api.py +0 -84
- jaseci/extens/api/graph_api.py +0 -167
- jaseci/extens/api/health_api.py +0 -20
- jaseci/extens/api/interface.py +0 -268
- jaseci/extens/api/jac_api.py +0 -171
- jaseci/extens/api/jsorc_api.py +0 -316
- jaseci/extens/api/logger_api.py +0 -89
- jaseci/extens/api/master_api.py +0 -133
- jaseci/extens/api/object_api.py +0 -101
- jaseci/extens/api/prometheus_api.py +0 -74
- jaseci/extens/api/queue_api.py +0 -140
- jaseci/extens/api/sentinel_api.py +0 -270
- jaseci/extens/api/super_api.py +0 -64
- jaseci/extens/api/tests/__init__.py +0 -0
- jaseci/extens/api/tests/test_architype_api.py +0 -66
- jaseci/extens/api/tests/test_global_api.py +0 -179
- jaseci/extens/api/tests/test_graph_api.py +0 -64
- jaseci/extens/api/tests/test_logger_api.py +0 -43
- jaseci/extens/api/tests/test_object_api.py +0 -20
- jaseci/extens/api/tests/test_sentinel_api.py +0 -66
- jaseci/extens/api/tests/test_uncommon.py +0 -107
- jaseci/extens/api/tests/test_user_api.py +0 -32
- jaseci/extens/api/tests/test_walker_api.py +0 -316
- jaseci/extens/api/user_api.py +0 -144
- jaseci/extens/api/walker_api.py +0 -298
- jaseci/extens/api/webhook_api.py +0 -74
- jaseci/extens/svc/__init__.py +0 -0
- jaseci/extens/svc/elastic_svc.py +0 -366
- jaseci/extens/svc/kube_svc.py +0 -432
- jaseci/extens/svc/mail_svc.py +0 -156
- jaseci/extens/svc/prome_svc.py +0 -378
- jaseci/extens/svc/redis_svc.py +0 -63
- jaseci/extens/svc/storage_svc.py +0 -193
- jaseci/extens/svc/stripe_svc.py +0 -51
- jaseci/extens/svc/task_svc.py +0 -155
- jaseci/extens/svc/tasks.py +0 -302
- jaseci/jac/__init__.py +0 -0
- jaseci/jac/interpreter/__init__.py +0 -0
- jaseci/jac/interpreter/architype_interp.py +0 -214
- jaseci/jac/interpreter/interp.py +0 -1783
- jaseci/jac/interpreter/sentinel_interp.py +0 -257
- jaseci/jac/interpreter/tests/__init__.py +0 -0
- jaseci/jac/interpreter/tests/test_interp.py +0 -42
- jaseci/jac/interpreter/walker_interp.py +0 -248
- jaseci/jac/ir/__init__.py +0 -0
- jaseci/jac/ir/ast.py +0 -73
- jaseci/jac/ir/ast_builder.py +0 -249
- jaseci/jac/ir/jac_code.py +0 -152
- jaseci/jac/ir/passes/__init__.py +0 -6
- jaseci/jac/ir/passes/ast_prune_pass.py +0 -9
- jaseci/jac/ir/passes/codegen_pass.py +0 -244
- jaseci/jac/ir/passes/ir_pass.py +0 -29
- jaseci/jac/ir/passes/printer_pass.py +0 -23
- jaseci/jac/ir/passes/pt_prune_pass.py +0 -29
- jaseci/jac/ir/passes/schedule.py +0 -23
- jaseci/jac/ir/passes/stats_pass.py +0 -16
- jaseci/jac/jac.g4 +0 -450
- jaseci/jac/jac_parse/__init__.py +0 -0
- jaseci/jac/jac_parse/jacLexer.py +0 -809
- jaseci/jac/jac_parse/jacListener.py +0 -853
- jaseci/jac/jac_parse/jacParser.py +0 -9192
- jaseci/jac/jac_set.py +0 -119
- jaseci/jac/jsci_vm/__init__.py +0 -0
- jaseci/jac/jsci_vm/disasm.py +0 -94
- jaseci/jac/jsci_vm/inst_ptr.py +0 -31
- jaseci/jac/jsci_vm/machine.py +0 -188
- jaseci/jac/jsci_vm/op_codes.py +0 -82
- jaseci/jac/jsci_vm/tests/__init__.py +0 -0
- jaseci/jac/jsci_vm/tests/test_codegen.py +0 -31
- jaseci/jac/machine/__init__.py +0 -0
- jaseci/jac/machine/jac_scope.py +0 -85
- jaseci/jac/machine/jac_value.py +0 -226
- jaseci/jac/machine/machine_state.py +0 -383
- jaseci/jac/tests/__init__.py +0 -0
- jaseci/jac/tests/book_code.py +0 -624
- jaseci/jac/tests/test_book.py +0 -380
- jaseci/jac/tests/test_lang_14.py +0 -49
- jaseci/jsorc/__init__.py +0 -7
- jaseci/jsorc/jsorc.py +0 -642
- jaseci/jsorc/jsorc_settings.py +0 -211
- jaseci/jsorc/jsorc_utils.py +0 -298
- jaseci/jsorc/live_actions.py +0 -364
- jaseci/jsorc/manifests/__init__.py +0 -0
- jaseci/jsorc/manifests/database.yaml +0 -109
- jaseci/jsorc/manifests/elastic.yaml +0 -6024
- jaseci/jsorc/manifests/prometheus.yaml +0 -1383
- jaseci/jsorc/manifests/redis.yaml +0 -64
- jaseci/jsorc/memory.py +0 -258
- jaseci/jsorc/redis.py +0 -139
- jaseci/jsorc/remote_actions.py +0 -157
- jaseci/jsorc/tests/__init__.py +0 -0
- jaseci/jsorc/tests/test_actions.py +0 -542
- jaseci/jsorc/tests/test_jsorc.py +0 -112
- jaseci/prim/__init__.py +0 -0
- jaseci/prim/ability.py +0 -93
- jaseci/prim/architype.py +0 -89
- jaseci/prim/edge.py +0 -172
- jaseci/prim/element.py +0 -233
- jaseci/prim/graph.py +0 -26
- jaseci/prim/master.py +0 -64
- jaseci/prim/node.py +0 -532
- jaseci/prim/obj_mixins.py +0 -235
- jaseci/prim/sentinel.py +0 -281
- jaseci/prim/super_master.py +0 -31
- jaseci/prim/walker.py +0 -261
- jaseci/svc/__init__.py +0 -0
- jaseci/tests/__init__.py +0 -0
- jaseci/tests/infer.py +0 -39
- jaseci/tests/jac_test_code.py +0 -1293
- jaseci/tests/jac_test_progs.py +0 -774
- jaseci/tests/test_core.py +0 -153
- jaseci/tests/test_jac.py +0 -824
- jaseci/tests/test_node.py +0 -89
- jaseci/tests/test_progs.py +0 -702
- jaseci/tests/test_stack.py +0 -220
- jaseci/tests/test_stripe.py +0 -225
- jaseci/utils/__init__.py +0 -0
- jaseci/utils/actions/__init__.py +0 -0
- jaseci/utils/actions/actions_manager.py +0 -254
- jaseci/utils/actions/actions_optimizer.py +0 -516
- jaseci/utils/actions/actions_state.py +0 -95
- jaseci/utils/file_handler.py +0 -171
- jaseci/utils/gprof2dot.py +0 -3786
- jaseci/utils/id_list.py +0 -168
- jaseci/utils/json_handler.py +0 -70
- jaseci/utils/log_utils.py +0 -57
- jaseci/utils/test_core.py +0 -62
- jaseci/utils/utils.py +0 -387
- jaseci-1.4.2.5.dist-info/LICENSE +0 -21
- jaseci-1.4.2.5.dist-info/METADATA +0 -39
- jaseci-1.4.2.5.dist-info/RECORD +0 -184
- jaseci-1.4.2.5.dist-info/entry_points.txt +0 -3
- 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
|