feldera 0.118.0__py3-none-any.whl → 0.119.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 feldera might be problematic. Click here for more details.
- feldera/pipeline.py +9 -4
- feldera/rest/feldera_client.py +79 -4
- feldera/stats.py +1 -1
- {feldera-0.118.0.dist-info → feldera-0.119.0.dist-info}/METADATA +2 -2
- {feldera-0.118.0.dist-info → feldera-0.119.0.dist-info}/RECORD +7 -7
- {feldera-0.118.0.dist-info → feldera-0.119.0.dist-info}/WHEEL +0 -0
- {feldera-0.118.0.dist-info → feldera-0.119.0.dist-info}/top_level.txt +0 -0
feldera/pipeline.py
CHANGED
|
@@ -142,6 +142,7 @@ class Pipeline:
|
|
|
142
142
|
data: Dict | list,
|
|
143
143
|
update_format: str = "raw",
|
|
144
144
|
force: bool = False,
|
|
145
|
+
wait: bool = True,
|
|
145
146
|
):
|
|
146
147
|
"""
|
|
147
148
|
Push this JSON data to the specified table of the pipeline.
|
|
@@ -155,6 +156,7 @@ class Pipeline:
|
|
|
155
156
|
:param update_format: The update format of the JSON data to be pushed to the pipeline. Must be one of:
|
|
156
157
|
"raw", "insert_delete". https://docs.feldera.com/formats/json#the-insertdelete-format
|
|
157
158
|
:param force: `True` to push data even if the pipeline is paused. `False` by default.
|
|
159
|
+
:param wait: If True, blocks until this input has been processed by the pipeline
|
|
158
160
|
|
|
159
161
|
:raises ValueError: If the update format is invalid.
|
|
160
162
|
:raises FelderaAPIError: If the pipeline is not in a valid state to push data.
|
|
@@ -177,6 +179,7 @@ class Pipeline:
|
|
|
177
179
|
update_format=update_format,
|
|
178
180
|
array=array,
|
|
179
181
|
force=force,
|
|
182
|
+
wait=wait,
|
|
180
183
|
)
|
|
181
184
|
|
|
182
185
|
def pause_connector(self, table_name: str, connector_name: str):
|
|
@@ -372,7 +375,7 @@ method or use `Pipeline.resume()` to resume a paused pipeline."""
|
|
|
372
375
|
return
|
|
373
376
|
|
|
374
377
|
self.client.pause_pipeline(
|
|
375
|
-
self.name, "Unable to START the pipeline.\n", timeout_s
|
|
378
|
+
self.name, "Unable to START the pipeline.\n", wait=wait, timeout_s=timeout_s
|
|
376
379
|
)
|
|
377
380
|
self.__setup_output_listeners()
|
|
378
381
|
self.resume(timeout_s=timeout_s)
|
|
@@ -506,9 +509,11 @@ metrics"""
|
|
|
506
509
|
queue.put(_CallbackRunnerInstruction.RanToCompletion)
|
|
507
510
|
|
|
508
511
|
if len(self.views_tx) > 0:
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
queue.
|
|
512
|
+
while self.views_tx:
|
|
513
|
+
view = self.views_tx.pop()
|
|
514
|
+
for view_name, queue in view.items():
|
|
515
|
+
# block until the callback runner has been stopped
|
|
516
|
+
queue.join()
|
|
512
517
|
|
|
513
518
|
time.sleep(3)
|
|
514
519
|
self.client.stop_pipeline(
|
feldera/rest/feldera_client.py
CHANGED
|
@@ -8,7 +8,7 @@ from typing import Generator, Mapping
|
|
|
8
8
|
|
|
9
9
|
from feldera.rest.config import Config
|
|
10
10
|
from feldera.rest.feldera_config import FelderaConfig
|
|
11
|
-
from feldera.rest.errors import FelderaTimeoutError
|
|
11
|
+
from feldera.rest.errors import FelderaTimeoutError, FelderaAPIError
|
|
12
12
|
from feldera.rest.pipeline import Pipeline
|
|
13
13
|
from feldera.rest._httprequests import HttpRequests
|
|
14
14
|
from feldera.rest._helpers import client_version
|
|
@@ -67,7 +67,7 @@ class FelderaClient:
|
|
|
67
67
|
config = self.get_config()
|
|
68
68
|
version = client_version()
|
|
69
69
|
if config.version != version:
|
|
70
|
-
logging.
|
|
70
|
+
logging.warning(
|
|
71
71
|
f"Client is on version {version} while server is at "
|
|
72
72
|
f"{config.version}. There could be incompatibilities."
|
|
73
73
|
)
|
|
@@ -593,7 +593,9 @@ Reason: The pipeline is in a STOPPED state due to the following error:
|
|
|
593
593
|
update_format: str = "raw",
|
|
594
594
|
json_flavor: Optional[str] = None,
|
|
595
595
|
serialize: bool = True,
|
|
596
|
-
|
|
596
|
+
wait: bool = True,
|
|
597
|
+
wait_timeout_s: Optional[float] = None,
|
|
598
|
+
) -> str:
|
|
597
599
|
"""
|
|
598
600
|
Insert data into a pipeline
|
|
599
601
|
|
|
@@ -610,6 +612,11 @@ Reason: The pipeline is in a STOPPED state due to the following error:
|
|
|
610
612
|
"debezium_mysql", "snowflake", "kafka_connect_json_converter", "pandas"
|
|
611
613
|
:param data: The data to insert
|
|
612
614
|
:param serialize: If True, the data will be serialized to JSON. True by default
|
|
615
|
+
:param wait: If True, blocks until this input has been processed by the pipeline
|
|
616
|
+
:param wait_timeout_s: The timeout in seconds to wait for this set of
|
|
617
|
+
inputs to be processed by the pipeline. None by default
|
|
618
|
+
|
|
619
|
+
:returns: The completion token to this input.
|
|
613
620
|
"""
|
|
614
621
|
|
|
615
622
|
if format not in ["json", "csv"]:
|
|
@@ -671,7 +678,7 @@ Reason: The pipeline is in a STOPPED state due to the following error:
|
|
|
671
678
|
content_type = "text/csv"
|
|
672
679
|
data = bytes(str(data), "utf-8")
|
|
673
680
|
|
|
674
|
-
self.http.post(
|
|
681
|
+
resp = self.http.post(
|
|
675
682
|
path=f"/pipelines/{pipeline_name}/ingress/{table_name}",
|
|
676
683
|
params=params,
|
|
677
684
|
content_type=content_type,
|
|
@@ -679,6 +686,74 @@ Reason: The pipeline is in a STOPPED state due to the following error:
|
|
|
679
686
|
serialize=serialize,
|
|
680
687
|
)
|
|
681
688
|
|
|
689
|
+
token = resp.get("token")
|
|
690
|
+
if token is None:
|
|
691
|
+
raise FelderaAPIError("response did not contain a completion token", resp)
|
|
692
|
+
|
|
693
|
+
if not wait:
|
|
694
|
+
return token
|
|
695
|
+
|
|
696
|
+
self.wait_for_token(pipeline_name, token, timeout_s=wait_timeout_s)
|
|
697
|
+
|
|
698
|
+
return token
|
|
699
|
+
|
|
700
|
+
def wait_for_token(
|
|
701
|
+
self, pipeline_name: str, token: str, timeout_s: Optional[float] = 600
|
|
702
|
+
):
|
|
703
|
+
"""
|
|
704
|
+
Blocks until all records represented by this completion token have
|
|
705
|
+
been processed.
|
|
706
|
+
|
|
707
|
+
:param pipeline_name: The name of the pipeline
|
|
708
|
+
:param token: The token to check for completion
|
|
709
|
+
:param timeout_s: The amount of time in seconds to wait for the pipeline
|
|
710
|
+
to process these records. Default 600s
|
|
711
|
+
"""
|
|
712
|
+
|
|
713
|
+
params = {
|
|
714
|
+
"token": token,
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
start = time.monotonic()
|
|
718
|
+
end = start + timeout_s if timeout_s else None
|
|
719
|
+
initial_backoff = 0.1
|
|
720
|
+
max_backoff = 5
|
|
721
|
+
exponent = 1.2
|
|
722
|
+
retries = 0
|
|
723
|
+
|
|
724
|
+
while True:
|
|
725
|
+
if end:
|
|
726
|
+
if time.monotonic() > end:
|
|
727
|
+
raise FelderaTimeoutError(
|
|
728
|
+
f"timeout error: pipeline '{pipeline_name}' did not"
|
|
729
|
+
f" process records represented by token {token} within"
|
|
730
|
+
f" {timeout_s}"
|
|
731
|
+
)
|
|
732
|
+
|
|
733
|
+
resp = self.http.get(
|
|
734
|
+
path=f"/pipelines/{pipeline_name}/completion_status", params=params
|
|
735
|
+
)
|
|
736
|
+
|
|
737
|
+
status: Optional[str] = resp.get("status")
|
|
738
|
+
if status is None:
|
|
739
|
+
raise FelderaAPIError(
|
|
740
|
+
f"got empty status when checking for completion status for token: {token}",
|
|
741
|
+
resp,
|
|
742
|
+
)
|
|
743
|
+
|
|
744
|
+
if status.lower() == "complete":
|
|
745
|
+
break
|
|
746
|
+
|
|
747
|
+
elapsed = time.monotonic() - start
|
|
748
|
+
logging.debug(
|
|
749
|
+
f"still waiting for inputs represented by {token} to be processed; elapsed: {elapsed}s"
|
|
750
|
+
)
|
|
751
|
+
|
|
752
|
+
retries += 1
|
|
753
|
+
backoff = min(max_backoff, initial_backoff * (exponent**retries))
|
|
754
|
+
|
|
755
|
+
time.sleep(backoff)
|
|
756
|
+
|
|
682
757
|
def listen_to_pipeline(
|
|
683
758
|
self,
|
|
684
759
|
pipeline_name: str,
|
feldera/stats.py
CHANGED
|
@@ -16,7 +16,7 @@ class PipelineStatistics:
|
|
|
16
16
|
|
|
17
17
|
self.global_metrics: GlobalPipelineMetrics = GlobalPipelineMetrics()
|
|
18
18
|
self.suspend_error: Optional[Any] = None
|
|
19
|
-
self.inputs: Mapping[List[InputEndpointStatus
|
|
19
|
+
self.inputs: Mapping[List[InputEndpointStatus]] = {}
|
|
20
20
|
self.outputs: Mapping[List[OutputEndpointStatus]] = {}
|
|
21
21
|
|
|
22
22
|
@classmethod
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: feldera
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.119.0
|
|
4
4
|
Summary: The feldera python client
|
|
5
5
|
Author-email: Feldera Team <dev@feldera.com>
|
|
6
6
|
License: MIT
|
|
@@ -84,7 +84,7 @@ cd python && python3 -m pytest tests/
|
|
|
84
84
|
- This will detect and run all test files that match the pattern `test_*.py` or
|
|
85
85
|
`*_test.py`.
|
|
86
86
|
- By default, the tests expect a running Feldera instance at `http://localhost:8080`.
|
|
87
|
-
To override the default endpoint, set the `
|
|
87
|
+
To override the default endpoint, set the `FELDERA_HOST` environment variable.
|
|
88
88
|
|
|
89
89
|
To run tests from a specific file:
|
|
90
90
|
|
|
@@ -3,21 +3,21 @@ feldera/_callback_runner.py,sha256=-2hYG70cEkvz4BiOfUTARaH-2Rlv0Qcz-ilvodgyK10,4
|
|
|
3
3
|
feldera/_helpers.py,sha256=rN0WuGSCCQlXWFMimZUQrgs-LJAfUo074d79sLElncQ,3023
|
|
4
4
|
feldera/enums.py,sha256=MTHBojVANsdRnjbrzCyIOniDIUaH8nTYRfxB7QvajEE,9570
|
|
5
5
|
feldera/output_handler.py,sha256=64J3ljhOaKIhxdjOKYi-BUz_HnMwROfmN8eE-btYygU,1930
|
|
6
|
-
feldera/pipeline.py,sha256=
|
|
6
|
+
feldera/pipeline.py,sha256=ZkmIU0nxpXplCl7iLh6XtdiCZtkR5GGKW33J4gdt1ig,37821
|
|
7
7
|
feldera/pipeline_builder.py,sha256=a750hp5SgTmlyrobTHFh1fTaK9Ed4A5qnXaYRctRM-8,4250
|
|
8
8
|
feldera/runtime_config.py,sha256=MuYJPd5G_hnu_eDz4ge4BfYvSBSOvOEtv4NYh5sEwqU,4452
|
|
9
|
-
feldera/stats.py,sha256=
|
|
9
|
+
feldera/stats.py,sha256=eZxq51bUV3mlo6BW43DUHwmG1wpLs04rVECxOGojqxU,5026
|
|
10
10
|
feldera/rest/__init__.py,sha256=Eg-EKUU3RSTDcdxTR_7wNDnCly8VpXEzsZCQUmf-y2M,308
|
|
11
11
|
feldera/rest/_helpers.py,sha256=q7jWInKp9IiIli8N5o31lDG3hNUbcsJqufZXYHG04ps,222
|
|
12
12
|
feldera/rest/_httprequests.py,sha256=w8tD-_3spAf4vgalJQceIHQ7qw1uvxprDFM2oz3P5QU,7559
|
|
13
13
|
feldera/rest/config.py,sha256=DYzZKngDEhouTEwqVFd-rDrBN9tWqsU07Jl_BTT4mXs,1008
|
|
14
14
|
feldera/rest/errors.py,sha256=b4i2JjrbSmej7jdko_FL8UeXklLKenSipwMT80jowaM,1720
|
|
15
|
-
feldera/rest/feldera_client.py,sha256=
|
|
15
|
+
feldera/rest/feldera_client.py,sha256=tU99wyMDNkyHerom1QKeg1WZmno7bLNrIzbU2f98-7U,32855
|
|
16
16
|
feldera/rest/feldera_config.py,sha256=1pnGbLFMSLvp7Qh_OlPLALSKCSHIktNWKvx6gYU00U4,1374
|
|
17
17
|
feldera/rest/pipeline.py,sha256=Rmbflbwjvd86iZ5aSJ5b_bTSs6vgvEKQFwMZDtm0nxE,2835
|
|
18
18
|
feldera/rest/sql_table.py,sha256=qrw-YwMzx5T81zDefNO1KOx7EyypFz1vPwGBzSUB7kc,652
|
|
19
19
|
feldera/rest/sql_view.py,sha256=hN12mPM0mvwLCIPYywpb12s9Hd2Ws31IlTMXPriMisw,644
|
|
20
|
-
feldera-0.
|
|
21
|
-
feldera-0.
|
|
22
|
-
feldera-0.
|
|
23
|
-
feldera-0.
|
|
20
|
+
feldera-0.119.0.dist-info/METADATA,sha256=a-EKosH2QXmtKRGM2XhxxM-Q8G8kYUWd5j8xIaOq-Wc,4053
|
|
21
|
+
feldera-0.119.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
22
|
+
feldera-0.119.0.dist-info/top_level.txt,sha256=fB6yTqrQiO6RCbY1xP2T_mpPoTjDFtJvkJJodiee7d0,8
|
|
23
|
+
feldera-0.119.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|