omnata-plugin-runtime 0.8.0a188__py3-none-any.whl → 0.8.0a190__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.
- omnata_plugin_runtime/configuration.py +3 -1
- omnata_plugin_runtime/plugin_entrypoints.py +49 -40
- omnata_plugin_runtime/rate_limiting.py +15 -9
- {omnata_plugin_runtime-0.8.0a188.dist-info → omnata_plugin_runtime-0.8.0a190.dist-info}/METADATA +1 -1
- omnata_plugin_runtime-0.8.0a190.dist-info/RECORD +12 -0
- omnata_plugin_runtime-0.8.0a188.dist-info/RECORD +0 -12
- {omnata_plugin_runtime-0.8.0a188.dist-info → omnata_plugin_runtime-0.8.0a190.dist-info}/LICENSE +0 -0
- {omnata_plugin_runtime-0.8.0a188.dist-info → omnata_plugin_runtime-0.8.0a190.dist-info}/WHEEL +0 -0
@@ -19,7 +19,9 @@ if tuple(sys.version_info[:2]) >= (3, 9):
|
|
19
19
|
else:
|
20
20
|
# Python 3.8 and below
|
21
21
|
from typing_extensions import Annotated
|
22
|
+
from opentelemetry import trace
|
22
23
|
|
24
|
+
tracer = trace.get_tracer(__name__)
|
23
25
|
|
24
26
|
class MapperType(str, Enum):
|
25
27
|
FIELD_MAPPING_SELECTOR = "field_mapping_selector"
|
@@ -871,7 +873,7 @@ InboundSyncStreamsConfiguration.model_rebuild()
|
|
871
873
|
StoredFieldMappings.model_rebuild()
|
872
874
|
OutboundSyncConfigurationParameters.model_rebuild()
|
873
875
|
|
874
|
-
|
876
|
+
@tracer.start_as_current_span("get_secrets")
|
875
877
|
def get_secrets(oauth_secret_name: Optional[str], other_secrets_name: Optional[str]
|
876
878
|
) -> Dict[str, StoredConfigurationValue]:
|
877
879
|
connection_secrets = {}
|
@@ -39,7 +39,7 @@ from .rate_limiting import ApiLimits, RateLimitState
|
|
39
39
|
from opentelemetry import trace
|
40
40
|
|
41
41
|
IMPORT_DIRECTORY_NAME = "snowflake_import_directory"
|
42
|
-
|
42
|
+
tracer = trace.get_tracer(__name__)
|
43
43
|
|
44
44
|
class PluginEntrypoint:
|
45
45
|
"""
|
@@ -51,8 +51,7 @@ class PluginEntrypoint:
|
|
51
51
|
self, plugin_fqn: str, session: Session, module_name: str, class_name: str
|
52
52
|
):
|
53
53
|
logger.info(f"Initialising plugin entrypoint for {plugin_fqn}")
|
54
|
-
|
55
|
-
with self.tracer.start_as_current_span("plugin_initialization") as span:
|
54
|
+
with tracer.start_as_current_span("plugin_initialization") as span:
|
56
55
|
self._session = session
|
57
56
|
import_dir = sys._xoptions[IMPORT_DIRECTORY_NAME]
|
58
57
|
span.add_event("Adding plugin zip to path")
|
@@ -93,7 +92,7 @@ class PluginEntrypoint:
|
|
93
92
|
logger.add_extra('omnata.sync_branch.id', request.sync_branch_id)
|
94
93
|
logger.add_extra('omnata.sync_branch.name', request.sync_branch_name)
|
95
94
|
logger.info("Entered sync method")
|
96
|
-
with
|
95
|
+
with tracer.start_as_current_span("initialization") as span:
|
97
96
|
span.add_event("Fetching secrets")
|
98
97
|
|
99
98
|
request = TypeAdapter(SyncRequestPayload).validate_python(sync_request)
|
@@ -186,11 +185,11 @@ class PluginEntrypoint:
|
|
186
185
|
)
|
187
186
|
try:
|
188
187
|
self._plugin_instance._configuration_parameters = parameters
|
189
|
-
with
|
188
|
+
with tracer.start_as_current_span("invoke_plugin") as span:
|
190
189
|
with HttpRateLimiting(outbound_sync_request, parameters):
|
191
190
|
self._plugin_instance.sync_outbound(parameters, outbound_sync_request)
|
192
191
|
if self._plugin_instance.disable_background_workers is False:
|
193
|
-
with
|
192
|
+
with tracer.start_as_current_span("results_finalization") as span:
|
194
193
|
outbound_sync_request.apply_results_queue()
|
195
194
|
outbound_sync_request.apply_rate_limit_state()
|
196
195
|
if outbound_sync_request.deadline_reached:
|
@@ -246,12 +245,12 @@ class PluginEntrypoint:
|
|
246
245
|
inbound_sync_request.update_activity("Invoking plugin")
|
247
246
|
logger.info(f"inbound sync request: {inbound_sync_request}")
|
248
247
|
# plugin_instance._inbound_sync_request = outbound_sync_request
|
249
|
-
with
|
248
|
+
with tracer.start_as_current_span("invoke_plugin"):
|
250
249
|
with HttpRateLimiting(inbound_sync_request, parameters):
|
251
250
|
self._plugin_instance.sync_inbound(parameters, inbound_sync_request)
|
252
251
|
logger.info("Finished invoking plugin")
|
253
252
|
if self._plugin_instance.disable_background_workers is False:
|
254
|
-
with
|
253
|
+
with tracer.start_as_current_span("results_finalization") as span:
|
255
254
|
inbound_sync_request.update_activity("Staging remaining records")
|
256
255
|
logger.info("Calling apply_results_queue")
|
257
256
|
inbound_sync_request.apply_results_queue()
|
@@ -304,6 +303,8 @@ class PluginEntrypoint:
|
|
304
303
|
sync_parameters: Dict,
|
305
304
|
current_form_parameters: Optional[Dict],
|
306
305
|
):
|
306
|
+
if function_name is None:
|
307
|
+
function_name = f"{sync_direction}_configuration_form"
|
307
308
|
logger.add_extra('omnata.operation', 'configuration_form')
|
308
309
|
logger.add_extra('omnata.connection.connectivity_option', connectivity_option)
|
309
310
|
logger.add_extra('omnata.connection.connection_method', connection_method)
|
@@ -349,9 +350,10 @@ class PluginEntrypoint:
|
|
349
350
|
parameters.access_token_secret_name = oauth_secret_name
|
350
351
|
the_function = getattr(
|
351
352
|
self._plugin_instance,
|
352
|
-
function_name
|
353
|
+
function_name
|
353
354
|
)
|
354
|
-
|
355
|
+
with tracer.start_as_current_span("invoke_plugin"):
|
356
|
+
script_result = the_function(parameters)
|
355
357
|
if isinstance(script_result, BaseModel):
|
356
358
|
script_result = script_result.model_dump()
|
357
359
|
elif isinstance(script_result, List):
|
@@ -393,8 +395,8 @@ class PluginEntrypoint:
|
|
393
395
|
)
|
394
396
|
if oauth_secret_name is not None:
|
395
397
|
parameters.access_token_secret_name = oauth_secret_name
|
396
|
-
|
397
|
-
|
398
|
+
with tracer.start_as_current_span("invoke_plugin"):
|
399
|
+
script_result = self._plugin_instance.inbound_stream_list(parameters)
|
398
400
|
if isinstance(script_result, BaseModel):
|
399
401
|
script_result = script_result.model_dump()
|
400
402
|
elif isinstance(script_result, List):
|
@@ -428,19 +430,21 @@ class PluginEntrypoint:
|
|
428
430
|
logger.add_extra('omnata.connection.connectivity_option', connectivity_option)
|
429
431
|
connectivity_option = TypeAdapter(ConnectivityOption).validate_python(connectivity_option)
|
430
432
|
logger.info("Entered connection_form method")
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
433
|
+
with tracer.start_as_current_span("invoke_plugin"):
|
434
|
+
if self._plugin_instance.connection_form.__code__.co_argcount==1:
|
435
|
+
form: List[ConnectionMethod] = self._plugin_instance.connection_form()
|
436
|
+
else:
|
437
|
+
form: List[ConnectionMethod] = self._plugin_instance.connection_form(connectivity_option)
|
435
438
|
return [f.model_dump() for f in form]
|
436
439
|
|
437
440
|
def create_billing_events(self, session, event_request: Dict):
|
438
441
|
logger.add_extra('omnata.operation', 'create_billing_events')
|
439
442
|
logger.info("Entered create_billing_events method")
|
440
443
|
request = TypeAdapter(BillingEventRequest).validate_python(event_request)
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
+
with tracer.start_as_current_span("invoke_plugin"):
|
445
|
+
events: List[SnowflakeBillingEvent] = self._plugin_instance.create_billing_events(
|
446
|
+
request
|
447
|
+
)
|
444
448
|
# create each billing event, waiting a second between each one
|
445
449
|
first_time = True
|
446
450
|
for billing_event in events:
|
@@ -527,31 +531,35 @@ class PluginEntrypoint:
|
|
527
531
|
)
|
528
532
|
if oauth_secret_name is not None:
|
529
533
|
parameters.access_token_secret_name = oauth_secret_name
|
530
|
-
|
531
|
-
|
532
|
-
|
534
|
+
with tracer.start_as_current_span("invoke_plugin"):
|
535
|
+
connect_response = self._plugin_instance.connect(
|
536
|
+
parameters=parameters
|
537
|
+
)
|
533
538
|
# the connect method can also return more network addresses. If so, we need to update the
|
534
539
|
# network rule associated with the external access integration
|
535
540
|
if connect_response is None:
|
536
541
|
raise ValueError("Plugin did not return a ConnectResponse object from the connect method")
|
537
542
|
if connect_response.network_addresses is not None:
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
f"
|
554
|
-
|
543
|
+
with tracer.start_as_current_span("network_rule_update") as network_rule_update_span:
|
544
|
+
network_rule_update_span.add_event("Retrieving existing network rule")
|
545
|
+
existing_rule_result = self._session.sql(
|
546
|
+
f"desc network rule {network_rule_name}"
|
547
|
+
).collect()
|
548
|
+
rule_values: List[str] = existing_rule_result[0].value_list.split(",")
|
549
|
+
rule_values = [r for r in rule_values if r != '']
|
550
|
+
logger.info(f"Existing rules for {network_rule_name}: {rule_values}")
|
551
|
+
for network_address in connect_response.network_addresses:
|
552
|
+
if network_address not in rule_values:
|
553
|
+
rule_values.append(network_address)
|
554
|
+
#if len(rule_values)==0:
|
555
|
+
# logger.info("No network addresses for plugin, adding localhost")
|
556
|
+
# rule_values.append("https://localhost")
|
557
|
+
logger.info(f"New rules for {network_rule_name}: {rule_values}")
|
558
|
+
rule_values_string = ",".join([f"'{value}'" for value in rule_values])
|
559
|
+
network_rule_update_span.add_event("Updating network rule")
|
560
|
+
self._session.sql(
|
561
|
+
f"alter network rule {network_rule_name} set value_list = ({rule_values_string})"
|
562
|
+
).collect()
|
555
563
|
|
556
564
|
return connect_response.model_dump()
|
557
565
|
|
@@ -578,7 +586,8 @@ class PluginEntrypoint:
|
|
578
586
|
)
|
579
587
|
if oauth_secret_name is not None:
|
580
588
|
connection_parameters.access_token_secret_name = oauth_secret_name
|
581
|
-
|
589
|
+
with tracer.start_as_current_span("invoke_plugin"):
|
590
|
+
response: List[ApiLimits] = self._plugin_instance.api_limits(connection_parameters)
|
582
591
|
return [api_limit.model_dump() for api_limit in response]
|
583
592
|
|
584
593
|
def outbound_record_validator(
|
@@ -19,6 +19,9 @@ from .logging import logger
|
|
19
19
|
import pytz
|
20
20
|
from requests.adapters import HTTPAdapter
|
21
21
|
from urllib3.util.retry import Retry
|
22
|
+
from opentelemetry import trace
|
23
|
+
|
24
|
+
tracer = trace.get_tracer(__name__)
|
22
25
|
|
23
26
|
TimeUnitType = Literal["second", "minute", "hour", "day"]
|
24
27
|
|
@@ -383,11 +386,12 @@ class RetryWithLogging(Retry):
|
|
383
386
|
retry_after = self.get_retry_after(response)
|
384
387
|
if retry_after:
|
385
388
|
logger.info(f"Retrying after {retry_after} seconds due to Retry-After header")
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
389
|
+
with tracer.start_as_current_span("http_retry_wait"):
|
390
|
+
if self.thread_cancellation_token is None:
|
391
|
+
time.sleep(retry_after)
|
392
|
+
else:
|
393
|
+
if self.thread_cancellation_token.wait(retry_after):
|
394
|
+
raise InterruptedWhileWaitingException(message="The sync was interrupted while waiting for rate limiting to expire")
|
391
395
|
return True
|
392
396
|
return False
|
393
397
|
|
@@ -504,8 +508,9 @@ class RateLimitedSession(requests.Session):
|
|
504
508
|
raise InterruptedWhileWaitingException(message=f"The rate limiting wait time ({wait_time} seconds) would exceed the run deadline")
|
505
509
|
logger.info(f"Waiting for {wait_time} seconds before retrying {method} request to {url}")
|
506
510
|
# if wait() returns true, it means that the thread was cancelled
|
507
|
-
|
508
|
-
|
511
|
+
with tracer.start_as_current_span("http_retry_wait"):
|
512
|
+
if self.thread_cancellation_token.wait(wait_time):
|
513
|
+
raise InterruptedWhileWaitingException(message="The sync was interrupted while waiting for rate limiting to expire")
|
509
514
|
else:
|
510
515
|
current_url_retries = self.increment_retries(url)
|
511
516
|
if current_url_retries >= self.max_retries:
|
@@ -514,8 +519,9 @@ class RateLimitedSession(requests.Session):
|
|
514
519
|
if datetime.datetime.now(pytz.UTC) + datetime.timedelta(seconds=backoff_time) > self.run_deadline:
|
515
520
|
raise InterruptedWhileWaitingException(message=f"The rate limiting backoff time ({backoff_time} seconds) would exceed the run deadline")
|
516
521
|
logger.info(f"Waiting for {backoff_time} seconds before retrying {method} request to {url}")
|
517
|
-
|
518
|
-
|
522
|
+
with tracer.start_as_current_span("http_retry_wait"):
|
523
|
+
if self.thread_cancellation_token.wait(backoff_time):
|
524
|
+
raise InterruptedWhileWaitingException(message="The sync was interrupted while waiting for rate limiting backoff")
|
519
525
|
else:
|
520
526
|
self.set_retries(url,0) # Reset retries if the request is successful
|
521
527
|
return response
|
@@ -0,0 +1,12 @@
|
|
1
|
+
omnata_plugin_runtime/__init__.py,sha256=MS9d1whnfT_B3-ThqZ7l63QeC_8OEKTuaYV5wTwRpBA,1576
|
2
|
+
omnata_plugin_runtime/api.py,sha256=tVi4KLL0v5N3yz3Ie0kSyFemryu572gCbtSRfWN6wBU,6523
|
3
|
+
omnata_plugin_runtime/configuration.py,sha256=uMGMqKYy4XmntX1ROungUwTJXeY2ciczAb_PtRCFZZI,38441
|
4
|
+
omnata_plugin_runtime/forms.py,sha256=ueodN2GIMS5N9fqebpY4uNGJnjEb9HcuaVQVfWH-cGg,19838
|
5
|
+
omnata_plugin_runtime/logging.py,sha256=u_Bo2v4jS3C_2E_Y8a7yfZZcIP-h5Mak_FPnFHUwFbU,4378
|
6
|
+
omnata_plugin_runtime/omnata_plugin.py,sha256=aggjb_CTTjhgqjS8CHPOm4ENU0jNcYoT6LC8yI1IeF4,130048
|
7
|
+
omnata_plugin_runtime/plugin_entrypoints.py,sha256=dK2mdH9-HRa4vjCso3SIblC72wRU2txDJJBBwMbruo0,32760
|
8
|
+
omnata_plugin_runtime/rate_limiting.py,sha256=6fn_h2vxcHbqqiW-OZ6FKfNYv_XlNvorsrCknVce2PA,25929
|
9
|
+
omnata_plugin_runtime-0.8.0a190.dist-info/LICENSE,sha256=rGaMQG3R3F5-JGDp_-rlMKpDIkg5n0SI4kctTk8eZSI,56
|
10
|
+
omnata_plugin_runtime-0.8.0a190.dist-info/METADATA,sha256=NUbYL0R296nnATkJJF4YAV4F8W47yrqiIJ70KNtoSXc,2148
|
11
|
+
omnata_plugin_runtime-0.8.0a190.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
12
|
+
omnata_plugin_runtime-0.8.0a190.dist-info/RECORD,,
|
@@ -1,12 +0,0 @@
|
|
1
|
-
omnata_plugin_runtime/__init__.py,sha256=MS9d1whnfT_B3-ThqZ7l63QeC_8OEKTuaYV5wTwRpBA,1576
|
2
|
-
omnata_plugin_runtime/api.py,sha256=tVi4KLL0v5N3yz3Ie0kSyFemryu572gCbtSRfWN6wBU,6523
|
3
|
-
omnata_plugin_runtime/configuration.py,sha256=5M7dmQu9BO2msES9Foa8fOKfWui7iPSExAJdj9TeI98,38329
|
4
|
-
omnata_plugin_runtime/forms.py,sha256=ueodN2GIMS5N9fqebpY4uNGJnjEb9HcuaVQVfWH-cGg,19838
|
5
|
-
omnata_plugin_runtime/logging.py,sha256=u_Bo2v4jS3C_2E_Y8a7yfZZcIP-h5Mak_FPnFHUwFbU,4378
|
6
|
-
omnata_plugin_runtime/omnata_plugin.py,sha256=aggjb_CTTjhgqjS8CHPOm4ENU0jNcYoT6LC8yI1IeF4,130048
|
7
|
-
omnata_plugin_runtime/plugin_entrypoints.py,sha256=z1NJpWvEj5TizCEU8YLnO5cWmeU8iSEsMK9CQaL47RA,32021
|
8
|
-
omnata_plugin_runtime/rate_limiting.py,sha256=JKtyz8mA9D0FSZgQplPusmk2rVclcjkwtE59fQQrQ_I,25610
|
9
|
-
omnata_plugin_runtime-0.8.0a188.dist-info/LICENSE,sha256=rGaMQG3R3F5-JGDp_-rlMKpDIkg5n0SI4kctTk8eZSI,56
|
10
|
-
omnata_plugin_runtime-0.8.0a188.dist-info/METADATA,sha256=OrGtX56IyJCjpFTsxkVu0IZI3Z9zJ5aHSzpgI0Mg3Bk,2148
|
11
|
-
omnata_plugin_runtime-0.8.0a188.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
12
|
-
omnata_plugin_runtime-0.8.0a188.dist-info/RECORD,,
|
{omnata_plugin_runtime-0.8.0a188.dist-info → omnata_plugin_runtime-0.8.0a190.dist-info}/LICENSE
RENAMED
File without changes
|
{omnata_plugin_runtime-0.8.0a188.dist-info → omnata_plugin_runtime-0.8.0a190.dist-info}/WHEEL
RENAMED
File without changes
|