mlrun 1.7.0rc5__py3-none-any.whl → 1.7.0rc6__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 mlrun might be problematic. Click here for more details.

Files changed (36) hide show
  1. mlrun/artifacts/base.py +2 -1
  2. mlrun/artifacts/plots.py +9 -5
  3. mlrun/config.py +8 -2
  4. mlrun/datastore/sources.py +5 -4
  5. mlrun/db/factory.py +1 -1
  6. mlrun/launcher/__init__.py +1 -1
  7. mlrun/launcher/base.py +1 -1
  8. mlrun/launcher/client.py +1 -1
  9. mlrun/launcher/factory.py +1 -1
  10. mlrun/launcher/local.py +1 -1
  11. mlrun/launcher/remote.py +1 -1
  12. mlrun/model_monitoring/api.py +6 -12
  13. mlrun/model_monitoring/application.py +21 -21
  14. mlrun/model_monitoring/applications/histogram_data_drift.py +130 -40
  15. mlrun/model_monitoring/batch.py +1 -42
  16. mlrun/model_monitoring/controller.py +1 -8
  17. mlrun/model_monitoring/features_drift_table.py +34 -22
  18. mlrun/model_monitoring/helpers.py +45 -4
  19. mlrun/model_monitoring/stream_processing.py +2 -0
  20. mlrun/projects/project.py +170 -16
  21. mlrun/run.py +69 -73
  22. mlrun/runtimes/__init__.py +35 -0
  23. mlrun/runtimes/base.py +1 -1
  24. mlrun/runtimes/nuclio/application/__init__.py +15 -0
  25. mlrun/runtimes/nuclio/application/application.py +283 -0
  26. mlrun/runtimes/nuclio/application/reverse_proxy.go +87 -0
  27. mlrun/runtimes/nuclio/function.py +50 -1
  28. mlrun/runtimes/pod.py +1 -1
  29. mlrun/serving/states.py +7 -19
  30. mlrun/utils/version/version.json +2 -2
  31. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc6.dist-info}/METADATA +1 -1
  32. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc6.dist-info}/RECORD +36 -33
  33. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc6.dist-info}/LICENSE +0 -0
  34. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc6.dist-info}/WHEEL +0 -0
  35. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc6.dist-info}/entry_points.txt +0 -0
  36. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc6.dist-info}/top_level.txt +0 -0
@@ -43,6 +43,8 @@ from .nuclio import (
43
43
  new_v2_model_server,
44
44
  nuclio_init_hook,
45
45
  )
46
+ from .nuclio.application import ApplicationRuntime
47
+ from .nuclio.serving import serving_subkind
46
48
  from .remotesparkjob import RemoteSparkRuntime
47
49
  from .sparkjob import Spark3Runtime
48
50
 
@@ -101,6 +103,7 @@ class RuntimeKinds:
101
103
  local = "local"
102
104
  handler = "handler"
103
105
  databricks = "databricks"
106
+ application = "application"
104
107
 
105
108
  @staticmethod
106
109
  def all():
@@ -115,6 +118,7 @@ class RuntimeKinds:
115
118
  RuntimeKinds.mpijob,
116
119
  RuntimeKinds.local,
117
120
  RuntimeKinds.databricks,
121
+ RuntimeKinds.application,
118
122
  ]
119
123
 
120
124
  @staticmethod
@@ -147,6 +151,7 @@ class RuntimeKinds:
147
151
  RuntimeKinds.remote,
148
152
  RuntimeKinds.nuclio,
149
153
  RuntimeKinds.serving,
154
+ RuntimeKinds.application,
150
155
  ]
151
156
 
152
157
  @staticmethod
@@ -211,6 +216,35 @@ class RuntimeKinds:
211
216
  # both spark and remote spark uses different mechanism for assigning images
212
217
  return kind not in [RuntimeKinds.spark, RuntimeKinds.remotespark]
213
218
 
219
+ @staticmethod
220
+ def resolve_nuclio_runtime(kind: str, sub_kind: str):
221
+ kind = kind.split(":")[0]
222
+ if kind not in RuntimeKinds.nuclio_runtimes():
223
+ raise ValueError(
224
+ f"Kind {kind} is not a nuclio runtime, available runtimes are {RuntimeKinds.nuclio_runtimes()}"
225
+ )
226
+
227
+ if sub_kind == serving_subkind:
228
+ return ServingRuntime()
229
+
230
+ if kind == RuntimeKinds.application:
231
+ return ApplicationRuntime()
232
+
233
+ runtime = RemoteRuntime()
234
+ runtime.spec.function_kind = sub_kind
235
+ return runtime
236
+
237
+ @staticmethod
238
+ def resolve_nuclio_sub_kind(kind):
239
+ is_nuclio = kind.startswith("nuclio")
240
+ sub_kind = kind[kind.find(":") + 1 :] if is_nuclio and ":" in kind else None
241
+ if kind == RuntimeKinds.serving:
242
+ is_nuclio = True
243
+ sub_kind = serving_subkind
244
+ elif kind == RuntimeKinds.application:
245
+ is_nuclio = True
246
+ return is_nuclio, sub_kind
247
+
214
248
 
215
249
  def get_runtime_class(kind: str):
216
250
  if kind == RuntimeKinds.mpijob:
@@ -228,6 +262,7 @@ def get_runtime_class(kind: str):
228
262
  RuntimeKinds.local: LocalRuntime,
229
263
  RuntimeKinds.remotespark: RemoteSparkRuntime,
230
264
  RuntimeKinds.databricks: DatabricksRuntime,
265
+ RuntimeKinds.application: ApplicationRuntime,
231
266
  }
232
267
 
233
268
  return kind_runtime_map[kind]
mlrun/runtimes/base.py CHANGED
@@ -786,7 +786,7 @@ class BaseRuntime(ModelObj):
786
786
  requirements: Optional[list[str]] = None,
787
787
  overwrite: bool = False,
788
788
  prepare_image_for_deploy: bool = True,
789
- requirements_file: str = "",
789
+ requirements_file: Optional[str] = "",
790
790
  ):
791
791
  """add package requirements from file or list to build spec.
792
792
 
@@ -0,0 +1,15 @@
1
+ # Copyright 2024 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from .application import ApplicationRuntime
@@ -0,0 +1,283 @@
1
+ # Copyright 2024 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ import pathlib
15
+
16
+ import nuclio
17
+
18
+ import mlrun.errors
19
+ from mlrun.common.schemas import AuthInfo
20
+ from mlrun.runtimes import RemoteRuntime
21
+ from mlrun.runtimes.nuclio import min_nuclio_versions
22
+ from mlrun.runtimes.nuclio.function import NuclioSpec, NuclioStatus
23
+
24
+
25
+ class ApplicationSpec(NuclioSpec):
26
+ _dict_fields = NuclioSpec._dict_fields + [
27
+ "internal_application_port",
28
+ ]
29
+
30
+ def __init__(
31
+ self,
32
+ command=None,
33
+ args=None,
34
+ image=None,
35
+ mode=None,
36
+ entry_points=None,
37
+ description=None,
38
+ replicas=None,
39
+ min_replicas=None,
40
+ max_replicas=None,
41
+ volumes=None,
42
+ volume_mounts=None,
43
+ env=None,
44
+ resources=None,
45
+ config=None,
46
+ base_spec=None,
47
+ no_cache=None,
48
+ source=None,
49
+ image_pull_policy=None,
50
+ function_kind=None,
51
+ build=None,
52
+ service_account=None,
53
+ readiness_timeout=None,
54
+ readiness_timeout_before_failure=None,
55
+ default_handler=None,
56
+ node_name=None,
57
+ node_selector=None,
58
+ affinity=None,
59
+ disable_auto_mount=False,
60
+ priority_class_name=None,
61
+ pythonpath=None,
62
+ workdir=None,
63
+ image_pull_secret=None,
64
+ tolerations=None,
65
+ preemption_mode=None,
66
+ security_context=None,
67
+ service_type=None,
68
+ add_templated_ingress_host_mode=None,
69
+ clone_target_dir=None,
70
+ state_thresholds=None,
71
+ disable_default_http_trigger=None,
72
+ internal_application_port=None,
73
+ ):
74
+ super().__init__(
75
+ command=command,
76
+ args=args,
77
+ image=image,
78
+ mode=mode,
79
+ entry_points=entry_points,
80
+ description=description,
81
+ replicas=replicas,
82
+ min_replicas=min_replicas,
83
+ max_replicas=max_replicas,
84
+ volumes=volumes,
85
+ volume_mounts=volume_mounts,
86
+ env=env,
87
+ resources=resources,
88
+ config=config,
89
+ base_spec=base_spec,
90
+ no_cache=no_cache,
91
+ source=source,
92
+ image_pull_policy=image_pull_policy,
93
+ function_kind=function_kind,
94
+ build=build,
95
+ service_account=service_account,
96
+ readiness_timeout=readiness_timeout,
97
+ readiness_timeout_before_failure=readiness_timeout_before_failure,
98
+ default_handler=default_handler,
99
+ node_name=node_name,
100
+ node_selector=node_selector,
101
+ affinity=affinity,
102
+ disable_auto_mount=disable_auto_mount,
103
+ priority_class_name=priority_class_name,
104
+ pythonpath=pythonpath,
105
+ workdir=workdir,
106
+ image_pull_secret=image_pull_secret,
107
+ tolerations=tolerations,
108
+ preemption_mode=preemption_mode,
109
+ security_context=security_context,
110
+ service_type=service_type,
111
+ add_templated_ingress_host_mode=add_templated_ingress_host_mode,
112
+ clone_target_dir=clone_target_dir,
113
+ state_thresholds=state_thresholds,
114
+ disable_default_http_trigger=disable_default_http_trigger,
115
+ )
116
+ self.internal_application_port = internal_application_port or 8080
117
+
118
+ @property
119
+ def internal_application_port(self):
120
+ return self._internal_application_port
121
+
122
+ @internal_application_port.setter
123
+ def internal_application_port(self, port):
124
+ port = int(port)
125
+ if port < 0 or port > 65535:
126
+ raise ValueError("Port must be in the range 0-65535")
127
+ self._internal_application_port = port
128
+
129
+
130
+ class ApplicationStatus(NuclioStatus):
131
+ def __init__(
132
+ self,
133
+ state=None,
134
+ nuclio_name=None,
135
+ address=None,
136
+ internal_invocation_urls=None,
137
+ external_invocation_urls=None,
138
+ build_pod=None,
139
+ container_image=None,
140
+ application_image=None,
141
+ sidecar_name=None,
142
+ ):
143
+ super().__init__(
144
+ state=state,
145
+ nuclio_name=nuclio_name,
146
+ address=address,
147
+ internal_invocation_urls=internal_invocation_urls,
148
+ external_invocation_urls=external_invocation_urls,
149
+ build_pod=build_pod,
150
+ container_image=container_image,
151
+ )
152
+ self.application_image = application_image or None
153
+ self.sidecar_name = sidecar_name or None
154
+
155
+
156
+ class ApplicationRuntime(RemoteRuntime):
157
+ kind = "application"
158
+
159
+ @min_nuclio_versions("1.12.7")
160
+ def __init__(self, spec=None, metadata=None):
161
+ super().__init__(spec=spec, metadata=metadata)
162
+
163
+ @property
164
+ def spec(self) -> ApplicationSpec:
165
+ return self._spec
166
+
167
+ @spec.setter
168
+ def spec(self, spec):
169
+ self._spec = self._verify_dict(spec, "spec", ApplicationSpec)
170
+
171
+ @property
172
+ def status(self) -> ApplicationStatus:
173
+ return self._status
174
+
175
+ @status.setter
176
+ def status(self, status):
177
+ self._status = self._verify_dict(status, "status", ApplicationStatus)
178
+
179
+ def set_internal_application_port(self, port: int):
180
+ self.spec.internal_application_port = port
181
+
182
+ def pre_deploy_validation(self):
183
+ super().pre_deploy_validation()
184
+ if not self.spec.config.get("spec.sidecars"):
185
+ raise mlrun.errors.MLRunBadRequestError(
186
+ "Application spec must include a sidecar configuration"
187
+ )
188
+
189
+ sidecars = self.spec.config["spec.sidecars"]
190
+ for sidecar in sidecars:
191
+ if not sidecar.get("image"):
192
+ raise mlrun.errors.MLRunBadRequestError(
193
+ "Application sidecar spec must include an image"
194
+ )
195
+
196
+ if not sidecar.get("ports"):
197
+ raise mlrun.errors.MLRunBadRequestError(
198
+ "Application sidecar spec must include at least one port"
199
+ )
200
+
201
+ ports = sidecar["ports"]
202
+ for port in ports:
203
+ if not port.get("containerPort"):
204
+ raise mlrun.errors.MLRunBadRequestError(
205
+ "Application sidecar port spec must include a containerPort"
206
+ )
207
+
208
+ if not port.get("name"):
209
+ raise mlrun.errors.MLRunBadRequestError(
210
+ "Application sidecar port spec must include a name"
211
+ )
212
+
213
+ if not sidecar.get("command") and sidecar.get("args"):
214
+ raise mlrun.errors.MLRunBadRequestError(
215
+ "Application sidecar spec must include a command if args are provided"
216
+ )
217
+
218
+ def deploy(
219
+ self,
220
+ project="",
221
+ tag="",
222
+ verbose=False,
223
+ auth_info: AuthInfo = None,
224
+ builder_env: dict = None,
225
+ force_build: bool = False,
226
+ ):
227
+ self._ensure_reverse_proxy_configurations()
228
+ self._configure_application_sidecar()
229
+ super().deploy(
230
+ project,
231
+ tag,
232
+ verbose,
233
+ auth_info,
234
+ builder_env,
235
+ force_build,
236
+ )
237
+
238
+ def _ensure_reverse_proxy_configurations(self):
239
+ if self.spec.build.functionSourceCode or self.status.container_image:
240
+ return
241
+
242
+ filename, handler = ApplicationRuntime.get_filename_and_handler()
243
+ name, spec, code = nuclio.build_file(
244
+ filename,
245
+ name=self.metadata.name,
246
+ handler=handler,
247
+ )
248
+ self.spec.function_handler = mlrun.utils.get_in(spec, "spec.handler")
249
+ self.spec.build.functionSourceCode = mlrun.utils.get_in(
250
+ spec, "spec.build.functionSourceCode"
251
+ )
252
+ self.spec.nuclio_runtime = mlrun.utils.get_in(spec, "spec.runtime")
253
+
254
+ def _configure_application_sidecar(self):
255
+ # Save the application image in the status to allow overriding it with the reverse proxy entry point
256
+ if self.spec.image and (
257
+ not self.status.application_image
258
+ or self.spec.image != self.status.container_image
259
+ ):
260
+ self.status.application_image = self.spec.image
261
+ self.spec.image = ""
262
+
263
+ if self.status.container_image:
264
+ self.from_image(self.status.container_image)
265
+ # nuclio implementation detail - when providing the image and emptying out the source code,
266
+ # nuclio skips rebuilding the image and simply takes the prebuilt image
267
+ self.spec.build.functionSourceCode = ""
268
+
269
+ self.status.sidecar_name = f"{self.metadata.name}-sidecar"
270
+ self.with_sidecar(
271
+ name=self.status.sidecar_name,
272
+ image=self.status.application_image,
273
+ ports=self.spec.internal_application_port,
274
+ command=self.spec.command,
275
+ args=self.spec.args,
276
+ )
277
+ self.set_env("SIDECAR_PORT", self.spec.internal_application_port)
278
+ self.set_env("SIDECAR_HOST", "http://localhost")
279
+
280
+ @classmethod
281
+ def get_filename_and_handler(cls) -> (str, str):
282
+ reverse_proxy_file_path = pathlib.Path(__file__).parent / "reverse_proxy.go"
283
+ return str(reverse_proxy_file_path), "Handler"
@@ -0,0 +1,87 @@
1
+ // Copyright 2024 Iguazio
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ package main
15
+
16
+ import (
17
+ "bytes"
18
+ "fmt"
19
+ "net/http"
20
+ "net/http/httptest"
21
+ "net/http/httputil"
22
+ "net/url"
23
+ "os"
24
+ "strings"
25
+
26
+ nuclio "github.com/nuclio/nuclio-sdk-go"
27
+ )
28
+
29
+ func Handler(context *nuclio.Context, event nuclio.Event) (interface{}, error) {
30
+ reverseProxy := context.UserData.(map[string]interface{})["reverseProxy"].(*httputil.ReverseProxy)
31
+ sidecarUrl := context.UserData.(map[string]interface{})["server"].(string)
32
+
33
+ // populate reverse proxy http request
34
+ httpRequest, err := http.NewRequest(event.GetMethod(), event.GetPath(), bytes.NewReader(event.GetBody()))
35
+ if err != nil {
36
+ context.Logger.ErrorWith("Failed to create a reverse proxy request")
37
+ return nil, err
38
+ }
39
+ for k, v := range event.GetHeaders() {
40
+ httpRequest.Header[k] = []string{v.(string)}
41
+ }
42
+ recorder := httptest.NewRecorder()
43
+ reverseProxy.ServeHTTP(recorder, httpRequest)
44
+
45
+ // send request to sidecar
46
+ context.Logger.InfoWith("Forwarding request to sidecar", "sidecarUrl", sidecarUrl)
47
+ response := recorder.Result()
48
+
49
+ headers := make(map[string]interface{})
50
+ for key, value := range response.Header {
51
+ headers[key] = value[0]
52
+ }
53
+
54
+ // let the processor calculate the content length
55
+ delete(headers, "Content-Length")
56
+ return nuclio.Response{
57
+ StatusCode: response.StatusCode,
58
+ Body: recorder.Body.Bytes(),
59
+ ContentType: response.Header.Get("Content-Type"),
60
+ Headers: headers,
61
+ }, nil
62
+ }
63
+
64
+ func InitContext(context *nuclio.Context) error {
65
+ sidecarHost := os.Getenv("SIDECAR_HOST")
66
+ sidecarPort := os.Getenv("SIDECAR_PORT")
67
+ if sidecarHost == "" {
68
+ sidecarHost = "http://localhost"
69
+ } else if !strings.Contains(sidecarHost, "://") {
70
+ sidecarHost = fmt.Sprintf("http://%s", sidecarHost)
71
+ }
72
+
73
+ // url for request forwarding
74
+ sidecarUrl := fmt.Sprintf("%s:%s", sidecarHost, sidecarPort)
75
+ parsedURL, err := url.Parse(sidecarUrl)
76
+ if err != nil {
77
+ context.Logger.ErrorWith("Failed to parse sidecar url", "sidecarUrl", sidecarUrl)
78
+ return err
79
+ }
80
+ reverseProxy := httputil.NewSingleHostReverseProxy(parsedURL)
81
+
82
+ context.UserData = map[string]interface{}{
83
+ "server": sidecarUrl,
84
+ "reverseProxy": reverseProxy,
85
+ }
86
+ return nil
87
+ }
@@ -291,6 +291,9 @@ class RemoteRuntime(KubeResource):
291
291
  def status(self, status):
292
292
  self._status = self._verify_dict(status, "status", NuclioStatus)
293
293
 
294
+ def pre_deploy_validation(self):
295
+ pass
296
+
294
297
  def set_config(self, key, value):
295
298
  self.spec.config[key] = value
296
299
  return self
@@ -603,7 +606,6 @@ class RemoteRuntime(KubeResource):
603
606
  return self.spec.command
604
607
 
605
608
  def _wait_for_function_deployment(self, db, verbose=False):
606
- text = ""
607
609
  state = ""
608
610
  last_log_timestamp = 1
609
611
  while state not in ["ready", "error", "unhealthy"]:
@@ -958,6 +960,53 @@ class RemoteRuntime(KubeResource):
958
960
  data = json.loads(data)
959
961
  return data
960
962
 
963
+ def with_sidecar(
964
+ self,
965
+ name: str = None,
966
+ image: str = None,
967
+ ports: typing.Optional[typing.Union[int, list[int]]] = None,
968
+ command: typing.Optional[str] = None,
969
+ args: typing.Optional[list[str]] = None,
970
+ ):
971
+ """
972
+ Add a sidecar container to the function pod
973
+ :param name: Sidecar container name.
974
+ :param image: Sidecar container image.
975
+ :param ports: Sidecar container ports to expose. Can be a single port or a list of ports.
976
+ :param command: Sidecar container command instead of the image entrypoint.
977
+ :param args: Sidecar container command args (requires command to be set).
978
+ """
979
+ name = name or f"{self.metadata.name}-sidecar"
980
+ sidecar = self._set_sidecar(name)
981
+ if image:
982
+ sidecar["image"] = image
983
+
984
+ ports = mlrun.utils.helpers.as_list(ports)
985
+ sidecar["ports"] = [
986
+ {
987
+ "name": "http",
988
+ "containerPort": port,
989
+ "protocol": "TCP",
990
+ }
991
+ for port in ports
992
+ ]
993
+
994
+ if command:
995
+ sidecar["command"] = command
996
+
997
+ if args:
998
+ sidecar["args"] = args
999
+
1000
+ def _set_sidecar(self, name: str) -> dict:
1001
+ self.spec.config.setdefault("spec.sidecars", [])
1002
+ sidecars = self.spec.config["spec.sidecars"]
1003
+ for sidecar in sidecars:
1004
+ if sidecar["name"] == name:
1005
+ return sidecar
1006
+
1007
+ sidecars.append({"name": name})
1008
+ return sidecars[-1]
1009
+
961
1010
  def _trigger_of_kind_exists(self, kind: str) -> bool:
962
1011
  if not self.spec.config:
963
1012
  return False
mlrun/runtimes/pod.py CHANGED
@@ -985,7 +985,7 @@ class KubeResource(BaseRuntime):
985
985
  _is_nested = True
986
986
 
987
987
  def __init__(self, spec=None, metadata=None):
988
- super().__init__(metadata, spec)
988
+ super().__init__(metadata=metadata, spec=spec)
989
989
  self.verbose = False
990
990
 
991
991
  @property
mlrun/serving/states.py CHANGED
@@ -1161,19 +1161,11 @@ class FlowStep(BaseStep):
1161
1161
  if self._controller:
1162
1162
  # async flow (using storey)
1163
1163
  event._awaitable_result = None
1164
- if self.context.is_mock:
1165
- resp = self._controller.emit(
1166
- event, return_awaitable_result=self._wait_for_result
1167
- )
1168
- if self._wait_for_result and resp:
1169
- return resp.await_result()
1170
- else:
1171
- resp_awaitable = self._controller.emit(
1172
- event, await_result=self._wait_for_result
1173
- )
1174
- if self._wait_for_result:
1175
- return resp_awaitable
1176
- return self._await_and_return_id(resp_awaitable, event)
1164
+ resp = self._controller.emit(
1165
+ event, return_awaitable_result=self._wait_for_result
1166
+ )
1167
+ if self._wait_for_result and resp:
1168
+ return resp.await_result()
1177
1169
  event = copy(event)
1178
1170
  event.body = {"id": event.id}
1179
1171
  return event
@@ -1568,12 +1560,8 @@ def _init_async_objects(context, steps):
1568
1560
  source_args = context.get_param("source_args", {})
1569
1561
  explicit_ack = is_explicit_ack_supported(context) and mlrun.mlconf.is_explicit_ack()
1570
1562
 
1571
- if context.is_mock:
1572
- source_class = storey.SyncEmitSource
1573
- else:
1574
- source_class = storey.AsyncEmitSource
1575
-
1576
- default_source = source_class(
1563
+ # TODO: Change to AsyncEmitSource once we can drop support for nuclio<1.12.10
1564
+ default_source = storey.SyncEmitSource(
1577
1565
  context=context,
1578
1566
  explicit_ack=explicit_ack,
1579
1567
  **source_args,
@@ -1,4 +1,4 @@
1
1
  {
2
- "git_commit": "d3324e482f4a4182ee0c8eda4af0d312718b599d",
3
- "version": "1.7.0-rc5"
2
+ "git_commit": "cbfd1ee5f41bee97ff90efbce14bac0a56b58dce",
3
+ "version": "1.7.0-rc6"
4
4
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mlrun
3
- Version: 1.7.0rc5
3
+ Version: 1.7.0rc6
4
4
  Summary: Tracking and config of machine learning runs
5
5
  Home-page: https://github.com/mlrun/mlrun
6
6
  Author: Yaron Haviv