gooddata-flight-server 1.34.0__py3-none-any.whl → 1.56.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.
- gooddata_flight_server/errors/error_info.py +34 -8
- gooddata_flight_server/server/flight_rpc/flight_server.py +4 -6
- gooddata_flight_server/server/flight_rpc/flight_service.py +1 -3
- gooddata_flight_server/tasks/task_executor.py +9 -0
- gooddata_flight_server/tasks/thread_task_executor.py +10 -2
- {gooddata_flight_server-1.34.0.dist-info → gooddata_flight_server-1.56.0.dist-info}/METADATA +10 -23
- {gooddata_flight_server-1.34.0.dist-info → gooddata_flight_server-1.56.0.dist-info}/RECORD +10 -11
- {gooddata_flight_server-1.34.0.dist-info → gooddata_flight_server-1.56.0.dist-info}/WHEEL +1 -2
- gooddata_flight_server-1.56.0.dist-info/entry_points.txt +2 -0
- gooddata_flight_server-1.34.0.data/scripts/gooddata-flight-server +0 -10
- gooddata_flight_server-1.34.0.dist-info/top_level.txt +0 -1
- {gooddata_flight_server-1.34.0.dist-info → gooddata_flight_server-1.56.0.dist-info/licenses}/LICENSE.txt +0 -0
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
# (C) 2024 GoodData Corporation
|
|
2
2
|
import base64
|
|
3
3
|
import traceback
|
|
4
|
-
from typing import Callable, Optional, Union
|
|
4
|
+
from typing import Callable, Optional, Union, cast
|
|
5
5
|
|
|
6
6
|
import orjson
|
|
7
7
|
import pyarrow.flight
|
|
8
8
|
|
|
9
9
|
from gooddata_flight_server.errors.error_code import ErrorCode
|
|
10
10
|
|
|
11
|
+
_ERROR_INFO_MAX_MSG = 256
|
|
12
|
+
_ERROR_INFO_MAX_DETAIL = 512
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _truncate_str_value(val: Optional[str], max_len: int) -> Optional[str]:
|
|
16
|
+
if val is None:
|
|
17
|
+
return None
|
|
18
|
+
|
|
19
|
+
if len(val) <= max_len:
|
|
20
|
+
return val
|
|
21
|
+
|
|
22
|
+
# no big deal that the actual max length is slightly exceeded
|
|
23
|
+
# all this truncating happens because ErrorInfo is eventually
|
|
24
|
+
# passed via gRPC headers which have 16k hard limit
|
|
25
|
+
return val[:max_len] + " [truncated]"
|
|
26
|
+
|
|
11
27
|
|
|
12
28
|
class ErrorInfo:
|
|
13
29
|
"""
|
|
@@ -22,15 +38,15 @@ class ErrorInfo:
|
|
|
22
38
|
body: Optional[bytes] = None,
|
|
23
39
|
code: int = 0,
|
|
24
40
|
) -> None:
|
|
25
|
-
self._msg = msg
|
|
26
|
-
self._detail: Optional[str] = detail
|
|
41
|
+
self._msg = cast(str, _truncate_str_value(msg, _ERROR_INFO_MAX_MSG))
|
|
42
|
+
self._detail: Optional[str] = _truncate_str_value(detail, _ERROR_INFO_MAX_DETAIL)
|
|
27
43
|
self._body: Optional[bytes] = body
|
|
28
44
|
self._code: int = code
|
|
29
45
|
|
|
30
46
|
@property
|
|
31
47
|
def msg(self) -> str:
|
|
32
48
|
"""
|
|
33
|
-
:return: human
|
|
49
|
+
:return: human-readable error message
|
|
34
50
|
"""
|
|
35
51
|
return self._msg
|
|
36
52
|
|
|
@@ -60,26 +76,36 @@ class ErrorInfo:
|
|
|
60
76
|
"""
|
|
61
77
|
Updates error message.
|
|
62
78
|
|
|
63
|
-
:param msg: new message
|
|
79
|
+
:param msg: new message, up to 256 characters; will be truncated if the limit is exceeded
|
|
64
80
|
:return: self, for call chaining sakes
|
|
65
81
|
"""
|
|
66
|
-
self._msg = msg
|
|
82
|
+
self._msg = cast(str, _truncate_str_value(msg, _ERROR_INFO_MAX_MSG))
|
|
83
|
+
|
|
67
84
|
return self
|
|
68
85
|
|
|
69
86
|
def with_detail(self, detail: Optional[str] = None) -> "ErrorInfo":
|
|
70
87
|
"""
|
|
71
88
|
Updates or resets the error detail.
|
|
72
89
|
|
|
73
|
-
:param detail: detail to set; if None, the detail stored in the meta will be removed; default is None
|
|
90
|
+
:param detail: detail to set; if None, the detail stored in the meta will be removed; default is None;
|
|
91
|
+
detail can be up to 512 characters; will be truncated if the limit is exceeded
|
|
74
92
|
:return: self, for call chaining sakes
|
|
75
93
|
"""
|
|
76
|
-
self._detail = detail
|
|
94
|
+
self._detail = _truncate_str_value(detail, _ERROR_INFO_MAX_DETAIL)
|
|
95
|
+
|
|
77
96
|
return self
|
|
78
97
|
|
|
79
98
|
def with_body(self, body: Optional[Union[bytes, str]]) -> "ErrorInfo":
|
|
80
99
|
"""
|
|
81
100
|
Updates or resets the error body.
|
|
82
101
|
|
|
102
|
+
IMPORTANT: the ErrorInfo (and thus the contents of `body`) are passed out via FlightError.extra_info
|
|
103
|
+
property. The Flight RPC implementations pass the `extra_info` via gRPC headers. In turn, the gRPC headers
|
|
104
|
+
do have size limit. Keep this in mind when designing the value of `body`.
|
|
105
|
+
|
|
106
|
+
If you set body that is too large, you will run into problems like this:
|
|
107
|
+
https://github.com/grpc/grpc/issues/37852.
|
|
108
|
+
|
|
83
109
|
:param body: body to set; if None, the body stored in the meta will be removed; default is None
|
|
84
110
|
:return: self, for call chaining sakes
|
|
85
111
|
"""
|
|
@@ -30,12 +30,10 @@ T = TypeVar("T")
|
|
|
30
30
|
P = ParamSpec("P")
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def rpc_decorator() ->
|
|
34
|
-
Callable[
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
]
|
|
38
|
-
):
|
|
33
|
+
def rpc_decorator() -> Callable[
|
|
34
|
+
[Callable[Concatenate[Any, pyarrow.flight.ServerCallContext, P], T]],
|
|
35
|
+
Callable[Concatenate[Any, pyarrow.flight.ServerCallContext, P], T],
|
|
36
|
+
]:
|
|
39
37
|
def _factory(
|
|
40
38
|
fun: Callable[Concatenate[Any, pyarrow.flight.ServerCallContext, P], T],
|
|
41
39
|
) -> Callable[Concatenate[Any, pyarrow.flight.ServerCallContext, P], T]:
|
|
@@ -264,9 +264,7 @@ class FlightRpcService:
|
|
|
264
264
|
def wait_for_stop(self, timeout: Optional[float] = None) -> bool:
|
|
265
265
|
if self._flight_shutdown_thread is None:
|
|
266
266
|
# this is really some mess in the caller code.. did not call stop() but tries to wait for it..
|
|
267
|
-
raise AssertionError(
|
|
268
|
-
"Flight server stop() was not issued yet attempting to wait for " "the server to stop."
|
|
269
|
-
)
|
|
267
|
+
raise AssertionError("Flight server stop() was not issued yet attempting to wait for the server to stop.")
|
|
270
268
|
|
|
271
269
|
if self._flight_shutdown_thread.is_alive():
|
|
272
270
|
self._flight_shutdown_thread.join(timeout=timeout)
|
|
@@ -54,6 +54,15 @@ class TaskExecutor(abc.ABC):
|
|
|
54
54
|
"""
|
|
55
55
|
raise NotImplementedError
|
|
56
56
|
|
|
57
|
+
@abc.abstractmethod
|
|
58
|
+
def get_task_submitted_timestamp(self, task_id: str) -> Optional[float]:
|
|
59
|
+
"""
|
|
60
|
+
Returns the timestamp of when the task with the given id was submitted.
|
|
61
|
+
:param task_id: task id to get the timestamp for
|
|
62
|
+
:return: Timestamp in seconds since epoch of when the task was submitted or None if there is no such task
|
|
63
|
+
"""
|
|
64
|
+
raise NotImplementedError
|
|
65
|
+
|
|
57
66
|
@abc.abstractmethod
|
|
58
67
|
def wait_for_result(self, task_id: str, timeout: Optional[float] = None) -> Optional[TaskExecutionResult]:
|
|
59
68
|
"""
|
|
@@ -565,6 +565,14 @@ class ThreadTaskExecutor(TaskExecutor, _TaskExecutionCallbacks):
|
|
|
565
565
|
execution.start()
|
|
566
566
|
self._metrics.queue_size.set(self._queue_size)
|
|
567
567
|
|
|
568
|
+
def get_task_submitted_timestamp(self, task_id: str) -> Optional[float]:
|
|
569
|
+
with self._task_lock:
|
|
570
|
+
execution = self._executions.get(task_id)
|
|
571
|
+
|
|
572
|
+
if execution is not None:
|
|
573
|
+
return execution.stats.created
|
|
574
|
+
return None
|
|
575
|
+
|
|
568
576
|
def wait_for_result(self, task_id: str, timeout: Optional[float] = None) -> Optional[TaskExecutionResult]:
|
|
569
577
|
with self._task_lock:
|
|
570
578
|
execution = self._executions.get(task_id)
|
|
@@ -597,8 +605,8 @@ class ThreadTaskExecutor(TaskExecutor, _TaskExecutionCallbacks):
|
|
|
597
605
|
return True
|
|
598
606
|
|
|
599
607
|
if execution is None:
|
|
600
|
-
# the task was not and is not running - cancel not
|
|
601
|
-
return
|
|
608
|
+
# the task was not and is not running - cancel not necessary
|
|
609
|
+
return True
|
|
602
610
|
|
|
603
611
|
return execution.cancel()
|
|
604
612
|
|
{gooddata_flight_server-1.34.0.dist-info → gooddata_flight_server-1.56.0.dist-info}/METADATA
RENAMED
|
@@ -1,28 +1,25 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: gooddata-flight-server
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.56.0
|
|
4
4
|
Summary: Flight RPC server to host custom functions
|
|
5
|
-
|
|
6
|
-
Author-email: support@gooddata.com
|
|
7
|
-
License: MIT
|
|
8
|
-
Project-URL: Documentation, https://gooddata-flight-server.readthedocs.io/en/v1.34.0
|
|
5
|
+
Project-URL: Documentation, https://gooddata-flight-server.readthedocs.io/en/v1.56.0
|
|
9
6
|
Project-URL: Source, https://github.com/gooddata/gooddata-python-sdk
|
|
10
|
-
|
|
7
|
+
Author-email: GoodData <support@gooddata.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE.txt
|
|
10
|
+
Keywords: analytics,business,cloud,custom functions,flight,flight rpc,gooddata,headless,headless-bi,intelligence,layer,metrics,native,rpc,semantic,sql
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Environment :: Console
|
|
13
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
18
|
Classifier: Topic :: Database
|
|
20
19
|
Classifier: Topic :: Scientific/Engineering
|
|
21
20
|
Classifier: Topic :: Software Development
|
|
22
21
|
Classifier: Typing :: Typed
|
|
23
|
-
Requires-Python: >=3.
|
|
24
|
-
Description-Content-Type: text/markdown
|
|
25
|
-
License-File: LICENSE.txt
|
|
22
|
+
Requires-Python: >=3.10
|
|
26
23
|
Requires-Dist: dynaconf<4.0.0,>=3.1.11
|
|
27
24
|
Requires-Dist: opentelemetry-api<=2.0.0,>=1.24.0
|
|
28
25
|
Requires-Dist: opentelemetry-sdk<=2.0.0,>=1.24.0
|
|
@@ -31,17 +28,7 @@ Requires-Dist: prometheus-client~=0.20.0
|
|
|
31
28
|
Requires-Dist: pyarrow>=16.1.0
|
|
32
29
|
Requires-Dist: readerwriterlock~=1.0.9
|
|
33
30
|
Requires-Dist: structlog<25.0.0,>=24.0.0
|
|
34
|
-
|
|
35
|
-
Dynamic: author-email
|
|
36
|
-
Dynamic: classifier
|
|
37
|
-
Dynamic: description
|
|
38
|
-
Dynamic: description-content-type
|
|
39
|
-
Dynamic: keywords
|
|
40
|
-
Dynamic: license
|
|
41
|
-
Dynamic: project-url
|
|
42
|
-
Dynamic: requires-dist
|
|
43
|
-
Dynamic: requires-python
|
|
44
|
-
Dynamic: summary
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
45
32
|
|
|
46
33
|
# GoodData Flight Server
|
|
47
34
|
|
|
@@ -8,7 +8,7 @@ gooddata_flight_server/config/__init__.py,sha256=QL4TGz0QQfsNakkgMkve9k8wiR73dfo
|
|
|
8
8
|
gooddata_flight_server/config/config.py,sha256=vMdBzGnBrxPCAsfJgpOxQKjxXl5xjEFNu32_4Bk5Qdw,17108
|
|
9
9
|
gooddata_flight_server/errors/__init__.py,sha256=QL4TGz0QQfsNakkgMkve9k8wiR73dfoOF2_18ESSPRE,33
|
|
10
10
|
gooddata_flight_server/errors/error_code.py,sha256=s7wcNlsGKG0PSPXNMBMQMekViZeaoJKWVboEL12kogE,5808
|
|
11
|
-
gooddata_flight_server/errors/error_info.py,sha256=
|
|
11
|
+
gooddata_flight_server/errors/error_info.py,sha256=akYJk-QT0O2GQno__yc67YAxG5iBm-Fz4JDG2MQ6y4I,18852
|
|
12
12
|
gooddata_flight_server/health/__init__.py,sha256=QL4TGz0QQfsNakkgMkve9k8wiR73dfoOF2_18ESSPRE,33
|
|
13
13
|
gooddata_flight_server/health/health_check_http_server.py,sha256=A-wJ5L22s4PtJisNSOolrABp703w-0rhvDKKev_iN9I,3393
|
|
14
14
|
gooddata_flight_server/health/server_health_monitor.py,sha256=vDe3Z5u5SPPG3RWGtrexzoJJ4HLFl7A38_hA6LfS71I,2690
|
|
@@ -24,26 +24,25 @@ gooddata_flight_server/server/auth/token_verifier_factory.py,sha256=P-ktBUcl7YNa
|
|
|
24
24
|
gooddata_flight_server/server/auth/token_verifier_impl.py,sha256=F3phLqscCNFKOm3eF7w_KSfmM5_Nf9Kh5R9Rtr63eTU,1626
|
|
25
25
|
gooddata_flight_server/server/flight_rpc/__init__.py,sha256=nfaUa69U3uZAB1udH6tza0se-3fhrsSurgPUQldoGnE,32
|
|
26
26
|
gooddata_flight_server/server/flight_rpc/flight_middleware.py,sha256=Yb44PkgIL8MlYTGSPzHcnII6x9Hxlw5Y88YKeKIFeQI,5738
|
|
27
|
-
gooddata_flight_server/server/flight_rpc/flight_server.py,sha256=
|
|
28
|
-
gooddata_flight_server/server/flight_rpc/flight_service.py,sha256=
|
|
27
|
+
gooddata_flight_server/server/flight_rpc/flight_server.py,sha256=i1-HByn0_MhRG-d6qOCiwk29LDB4M0e7UZqPoatJYA0,8973
|
|
28
|
+
gooddata_flight_server/server/flight_rpc/flight_service.py,sha256=LqdZPl999_y1BXNB6GBNGEEdEDv0Y6guqa-Daqw_lgg,10522
|
|
29
29
|
gooddata_flight_server/server/flight_rpc/server_methods.py,sha256=fCUndugFTlAUKG7rHpkmjQ_wkXIeRZty65WAeIhS1r0,7708
|
|
30
30
|
gooddata_flight_server/tasks/__init__.py,sha256=QL4TGz0QQfsNakkgMkve9k8wiR73dfoOF2_18ESSPRE,33
|
|
31
31
|
gooddata_flight_server/tasks/base.py,sha256=e_8sV9JROtXo4rhAWXKvaPbKjm5T_0iFQyXnfGtLLwg,593
|
|
32
32
|
gooddata_flight_server/tasks/metrics.py,sha256=PY5FAp0lCEvsDX_xJNJ_soRZeTQ795OVh9CmBWSto7k,4085
|
|
33
33
|
gooddata_flight_server/tasks/task.py,sha256=9Qzhssw53vnlUf5ULL1LsrMrjpG1jAbQBXOc1apHBH4,6485
|
|
34
34
|
gooddata_flight_server/tasks/task_error.py,sha256=1Z2vJfRqRXaQk7fGMo2kGP9wLyxqngutjWyQIYpRNy8,2377
|
|
35
|
-
gooddata_flight_server/tasks/task_executor.py,sha256=
|
|
35
|
+
gooddata_flight_server/tasks/task_executor.py,sha256=xNO4UcBfdgs8aWr4KF7GNjfpXH5xy305sYyCArqFMu0,4139
|
|
36
36
|
gooddata_flight_server/tasks/task_result.py,sha256=1EqgP6xmhDDiWZYqJEOZxYZzUqAkRYF7ogsqNWAF4O4,12152
|
|
37
37
|
gooddata_flight_server/tasks/temporal_container.py,sha256=biNEUOSmp3D6iVoGBZnHo88tALdIwkb-SzR5besKmNo,8503
|
|
38
|
-
gooddata_flight_server/tasks/thread_task_executor.py,sha256=
|
|
38
|
+
gooddata_flight_server/tasks/thread_task_executor.py,sha256=QfluNnrm4LivPjfcXBJMyyUa-zX-EN65dnFayInd34A,22209
|
|
39
39
|
gooddata_flight_server/utils/__init__.py,sha256=nfaUa69U3uZAB1udH6tza0se-3fhrsSurgPUQldoGnE,32
|
|
40
40
|
gooddata_flight_server/utils/libc_utils.py,sha256=_ZwKeeB0lk2xh-gSC_7rc9felHu_hq9__GgLKZBI9sI,946
|
|
41
41
|
gooddata_flight_server/utils/logging.py,sha256=3sip4Xte5YHjZNyQEQVo96rCsknxG1JPj7cIbnz0iBo,6081
|
|
42
42
|
gooddata_flight_server/utils/methods_discovery.py,sha256=ZcBJU5dHBsnZD5zDXajE5merwCISfjHGcIlIWCQtNLY,3618
|
|
43
43
|
gooddata_flight_server/utils/otel_tracing.py,sha256=MfKFh0TkVSUmPC6f8Oobp5XSCYxAsQyS0UaSJQF1nCw,4540
|
|
44
|
-
gooddata_flight_server-1.
|
|
45
|
-
gooddata_flight_server-1.
|
|
46
|
-
gooddata_flight_server-1.
|
|
47
|
-
gooddata_flight_server-1.
|
|
48
|
-
gooddata_flight_server-1.
|
|
49
|
-
gooddata_flight_server-1.34.0.dist-info/RECORD,,
|
|
44
|
+
gooddata_flight_server-1.56.0.dist-info/METADATA,sha256=vAil4A3XK7f4mM5D3RX6UkgF1-ip3ziSSw4wwTADV78,29957
|
|
45
|
+
gooddata_flight_server-1.56.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
46
|
+
gooddata_flight_server-1.56.0.dist-info/entry_points.txt,sha256=uew4_TNofSLf7ppUmUNtD0o2KVDr-g_7Hl3D6Dsj71g,81
|
|
47
|
+
gooddata_flight_server-1.56.0.dist-info/licenses/LICENSE.txt,sha256=o90MhGat28171lD8r77bLXsSnvDVu9CQAsWxAzx1Z2E,1064
|
|
48
|
+
gooddata_flight_server-1.56.0.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
gooddata_flight_server
|
|
File without changes
|