helix.fhir.client.sdk 4.1.67__py3-none-any.whl → 4.2.18__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.
- helix_fhir_client_sdk/dictionary_parser.py +4 -0
- helix_fhir_client_sdk/fhir_auth_mixin.py +17 -10
- helix_fhir_client_sdk/fhir_client.py +161 -61
- helix_fhir_client_sdk/fhir_delete_mixin.py +62 -45
- helix_fhir_client_sdk/fhir_merge_mixin.py +188 -163
- helix_fhir_client_sdk/fhir_merge_resources_mixin.py +200 -9
- helix_fhir_client_sdk/fhir_patch_mixin.py +97 -81
- helix_fhir_client_sdk/fhir_update_mixin.py +71 -54
- helix_fhir_client_sdk/graph/simulated_graph_processor_mixin.py +5 -174
- helix_fhir_client_sdk/open_telemetry/__init__.py +0 -0
- helix_fhir_client_sdk/open_telemetry/attribute_names.py +7 -0
- helix_fhir_client_sdk/open_telemetry/span_names.py +12 -0
- helix_fhir_client_sdk/queue/request_queue_mixin.py +46 -119
- helix_fhir_client_sdk/responses/fhir_client_protocol.py +9 -1
- helix_fhir_client_sdk/responses/fhir_response_processor.py +73 -54
- helix_fhir_client_sdk/responses/get/fhir_get_bundle_response.py +0 -2
- helix_fhir_client_sdk/responses/merge/fhir_merge_resource_response_entry.py +30 -0
- helix_fhir_client_sdk/utilities/async_parallel_processor/v1/async_parallel_processor.py +1 -24
- helix_fhir_client_sdk/utilities/cache/request_cache.py +32 -43
- helix_fhir_client_sdk/utilities/retryable_aiohttp_client.py +184 -144
- helix_fhir_client_sdk/utilities/retryable_aiohttp_response.py +2 -1
- helix_fhir_client_sdk/utilities/url_checker.py +46 -12
- helix_fhir_client_sdk/validators/async_fhir_validator.py +3 -0
- helix_fhir_client_sdk-4.2.18.dist-info/METADATA +200 -0
- {helix_fhir_client_sdk-4.1.67.dist-info → helix_fhir_client_sdk-4.2.18.dist-info}/RECORD +32 -25
- tests/async/test_benchmark_compress.py +448 -0
- tests/async/test_benchmark_merge.py +506 -0
- tests/async/test_retryable_client_session_management.py +159 -0
- tests/test_fhir_client_clone.py +155 -0
- helix_fhir_client_sdk-4.1.67.dist-info/METADATA +0 -115
- {helix_fhir_client_sdk-4.1.67.dist-info → helix_fhir_client_sdk-4.2.18.dist-info}/WHEEL +0 -0
- {helix_fhir_client_sdk-4.1.67.dist-info → helix_fhir_client_sdk-4.2.18.dist-info}/licenses/LICENSE +0 -0
- {helix_fhir_client_sdk-4.1.67.dist-info → helix_fhir_client_sdk-4.2.18.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import json
|
|
3
2
|
from abc import ABC
|
|
4
3
|
from collections.abc import AsyncGenerator
|
|
@@ -124,23 +123,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
124
123
|
Yields:
|
|
125
124
|
FhirGetResponse objects representing retrieved resources
|
|
126
125
|
"""
|
|
127
|
-
def log_running_tasks(prefix: str = "") -> int:
|
|
128
|
-
"""Log currently running asyncio tasks"""
|
|
129
|
-
all_tasks = asyncio.all_tasks()
|
|
130
|
-
running_tasks = [t for t in all_tasks if not t.done()]
|
|
131
|
-
task_count = len(running_tasks)
|
|
132
|
-
waiting_tasks = [t for t in running_tasks if t._coro.cr_await is not None]
|
|
133
|
-
|
|
134
|
-
self._internal_logger.info(
|
|
135
|
-
f"{prefix} | ASYNC TASKS: Total Running={task_count} | "
|
|
136
|
-
f"all_tasks={len(all_tasks)} | "
|
|
137
|
-
)
|
|
138
|
-
print(f"{prefix} | ASYNC TASKS: Total Running={task_count} | all_tasks={len(all_tasks)} | waiting_tasks={len(waiting_tasks)}")
|
|
139
|
-
|
|
140
|
-
return task_count
|
|
141
|
-
|
|
142
|
-
log_running_tasks(prefix="[PROCESS_SIMULATE_GRAPH START]")
|
|
143
|
-
|
|
144
126
|
# Validate graph definition input
|
|
145
127
|
assert graph_json, "Graph JSON must be provided"
|
|
146
128
|
graph_definition: GraphDefinition = GraphDefinition.from_dict(graph_json)
|
|
@@ -153,7 +135,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
153
135
|
# Ensure bundle resources are not separated by default
|
|
154
136
|
self.separate_bundle_resources(False)
|
|
155
137
|
|
|
156
|
-
start_time = datetime.now()
|
|
157
138
|
# Log initial query parameters for debugging
|
|
158
139
|
if logger:
|
|
159
140
|
logger.info(
|
|
@@ -172,8 +153,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
172
153
|
if not isinstance(id_, list):
|
|
173
154
|
id_ = id_.split(",")
|
|
174
155
|
|
|
175
|
-
log_running_tasks(prefix="[BEFORE GRAPH PROCESSING]")
|
|
176
|
-
|
|
177
156
|
# Track resources that don't support ID-based search
|
|
178
157
|
id_search_unsupported_resources: list[str] = []
|
|
179
158
|
cache: RequestCache = input_cache if input_cache is not None else RequestCache()
|
|
@@ -193,8 +172,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
193
172
|
compare_hash=compare_hash,
|
|
194
173
|
)
|
|
195
174
|
|
|
196
|
-
log_running_tasks(prefix="[AFTER PARENT GET]")
|
|
197
|
-
|
|
198
175
|
# If no parent resources found, yield empty response and exit
|
|
199
176
|
parent_response_resource_count = parent_response.get_resource_count()
|
|
200
177
|
if parent_response_resource_count == 0:
|
|
@@ -230,8 +207,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
230
207
|
while len(parent_link_map):
|
|
231
208
|
new_parent_link_map: list[tuple[list[GraphDefinitionLink], FhirBundleEntryList]] = []
|
|
232
209
|
|
|
233
|
-
log_running_tasks(prefix="[BEFORE PROCESSING LINKS BATCH]")
|
|
234
|
-
|
|
235
210
|
# Parallel processing of links for each parent bundle
|
|
236
211
|
for link, parent_bundle_entries in parent_link_map:
|
|
237
212
|
link_responses: list[FhirGetResponse]
|
|
@@ -257,18 +232,16 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
257
232
|
):
|
|
258
233
|
child_responses.extend(link_responses)
|
|
259
234
|
|
|
260
|
-
log_running_tasks(prefix="[AFTER PROCESSING LINKS BATCH]")
|
|
261
|
-
|
|
262
235
|
# Update parent link map for next iteration
|
|
263
236
|
parent_link_map = new_parent_link_map
|
|
264
237
|
|
|
265
238
|
# Combine and process responses
|
|
266
239
|
parent_response = cast(FhirGetBundleResponse, parent_response.extend(child_responses))
|
|
267
|
-
parent_response = parent_response.remove_duplicates()
|
|
268
240
|
|
|
269
241
|
# Optional resource sorting
|
|
270
242
|
if sort_resources:
|
|
271
243
|
parent_response = parent_response.sort_resources()
|
|
244
|
+
|
|
272
245
|
# Prepare final response based on bundling preferences
|
|
273
246
|
full_response: FhirGetResponse
|
|
274
247
|
if separate_bundle_resources:
|
|
@@ -288,8 +261,8 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
288
261
|
f"start={graph_definition.start}, "
|
|
289
262
|
f"hits: {cache.cache_hits}, "
|
|
290
263
|
f"misses: {cache.cache_misses}"
|
|
291
|
-
f"total_time: {datetime.now() - start_time} in process simulate graph async"
|
|
292
264
|
)
|
|
265
|
+
|
|
293
266
|
# Yield the final response
|
|
294
267
|
yield full_response
|
|
295
268
|
|
|
@@ -376,10 +349,11 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
376
349
|
# Log detailed processing information
|
|
377
350
|
if parameters.logger:
|
|
378
351
|
parameters.logger.debug(
|
|
379
|
-
"Finished Processing link
|
|
352
|
+
"Finished Processing link"
|
|
380
353
|
+ f" | task_index: {context.task_index}/{context.total_task_count}"
|
|
381
354
|
+ (f" | path: {row.path}" if row.path else f" | target: {target_resource_type}")
|
|
382
355
|
+ f" | parallel_processor: {context.name}"
|
|
356
|
+
+ f" | end_time: {end_time}"
|
|
383
357
|
+ f" | duration: {end_time - start_time}"
|
|
384
358
|
+ f" | resource_count: {len(result)}"
|
|
385
359
|
)
|
|
@@ -433,30 +407,12 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
433
407
|
Yields:
|
|
434
408
|
FhirGetResponse objects for each processed target
|
|
435
409
|
"""
|
|
436
|
-
def log_running_tasks(prefix: str = "") -> int:
|
|
437
|
-
"""Log currently running asyncio tasks"""
|
|
438
|
-
all_tasks = asyncio.all_tasks()
|
|
439
|
-
running_tasks = [t for t in all_tasks if not t.done()]
|
|
440
|
-
task_count = len(running_tasks)
|
|
441
|
-
waiting_tasks = [t for t in running_tasks if t._coro.cr_await is not None]
|
|
442
|
-
|
|
443
|
-
self._internal_logger.info(
|
|
444
|
-
f"{prefix} | ASYNC TASKS: Total Running={task_count} | "
|
|
445
|
-
f"all_tasks={len(all_tasks)} | waiting_tasks={len(waiting_tasks)}"
|
|
446
|
-
)
|
|
447
|
-
print(f"{prefix} | ASYNC TASKS: Total Running={task_count} | all_tasks={len(all_tasks)} | waiting_tasks={len(waiting_tasks)}")
|
|
448
|
-
|
|
449
|
-
return task_count
|
|
450
|
-
|
|
451
410
|
# Validate input link
|
|
452
411
|
assert link, "GraphDefinitionLink must be provided"
|
|
453
412
|
|
|
454
413
|
if self._logger:
|
|
455
414
|
self._logger.debug(f"Processing link: {link.path} ")
|
|
456
415
|
|
|
457
|
-
log_running_tasks(prefix="[PROCESS_LINK START]")
|
|
458
|
-
start_time: datetime = datetime.now()
|
|
459
|
-
|
|
460
416
|
# Extract targets from the link
|
|
461
417
|
targets: list[GraphDefinitionTarget] = link.target
|
|
462
418
|
target_responses: list[FhirGetResponse]
|
|
@@ -488,13 +444,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
488
444
|
for target_response in target_responses:
|
|
489
445
|
yield target_response
|
|
490
446
|
|
|
491
|
-
end_time: datetime = datetime.now()
|
|
492
|
-
if logger:
|
|
493
|
-
logger.debug(
|
|
494
|
-
f"Finished Processing link async in {end_time - start_time} for path: {link.path}"
|
|
495
|
-
)
|
|
496
|
-
log_running_tasks(prefix="[PROCESS_LINK END]")
|
|
497
|
-
|
|
498
447
|
# noinspection PyUnusedLocal
|
|
499
448
|
async def process_target_async_parallel_function(
|
|
500
449
|
self,
|
|
@@ -535,7 +484,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
535
484
|
|
|
536
485
|
# Process the target asynchronously and collect responses
|
|
537
486
|
target_result: FhirGetResponse
|
|
538
|
-
start_time: datetime = datetime.now()
|
|
539
487
|
async for target_result in self._process_target_async(
|
|
540
488
|
# Target to process
|
|
541
489
|
target=row,
|
|
@@ -565,9 +513,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
565
513
|
# Collect each target result
|
|
566
514
|
result.append(target_result)
|
|
567
515
|
|
|
568
|
-
end_time: datetime = datetime.now()
|
|
569
|
-
if parameters.logger:
|
|
570
|
-
parameters.logger.debug(f"Completed process_target_async_parallel_function for target for {row} in {end_time - start_time}")
|
|
571
516
|
# Return the list of retrieved responses
|
|
572
517
|
return result
|
|
573
518
|
|
|
@@ -615,24 +560,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
615
560
|
Returns:
|
|
616
561
|
FhirGetResponse containing retrieved child resources
|
|
617
562
|
"""
|
|
618
|
-
def log_running_tasks(prefix: str = "") -> int:
|
|
619
|
-
"""Log currently running asyncio tasks"""
|
|
620
|
-
all_tasks = asyncio.all_tasks()
|
|
621
|
-
running_tasks = [t for t in all_tasks if not t.done()]
|
|
622
|
-
task_count = len(running_tasks)
|
|
623
|
-
waiting_tasks = [t for t in running_tasks if t._coro.cr_await is not None]
|
|
624
|
-
|
|
625
|
-
self._internal_logger.info(
|
|
626
|
-
f"{prefix} | ASYNC TASKS: Total Running={task_count} | "
|
|
627
|
-
f"all_tasks={len(all_tasks)} | waiting_tasks={len(waiting_tasks)}"
|
|
628
|
-
)
|
|
629
|
-
print(f"{prefix} | ASYNC TASKS: Total Running={task_count} | all_tasks={len(all_tasks)} | waiting_tasks={len(waiting_tasks)}")
|
|
630
|
-
|
|
631
|
-
return task_count
|
|
632
|
-
|
|
633
|
-
log_running_tasks(prefix="[PROCESS_CHILD_GROUP START]")
|
|
634
|
-
|
|
635
|
-
start_time: datetime = datetime.now()
|
|
636
563
|
# Retrieve resources using async method with parameters
|
|
637
564
|
(
|
|
638
565
|
child_response, # Retrieved child resources
|
|
@@ -655,9 +582,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
655
582
|
add_cached_bundles_to_result=add_cached_bundles_to_result,
|
|
656
583
|
)
|
|
657
584
|
|
|
658
|
-
log_running_tasks(prefix="[PROCESS_CHILD_GROUP END]")
|
|
659
|
-
|
|
660
|
-
end_time: datetime = datetime.now()
|
|
661
585
|
# Log detailed retrieval information if logger is available
|
|
662
586
|
if logger:
|
|
663
587
|
logger.info(
|
|
@@ -668,7 +592,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
668
592
|
+ f", count:{len(child_response.get_resource_type_and_ids())}"
|
|
669
593
|
+ f", cached:{cache_hits}"
|
|
670
594
|
+ f", {','.join(child_response.get_resource_type_and_ids())}"
|
|
671
|
-
+ f", duration:{end_time - start_time}"
|
|
672
595
|
)
|
|
673
596
|
|
|
674
597
|
# Return the retrieved child resources
|
|
@@ -705,22 +628,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
705
628
|
:param ifModifiedSince: ifModifiedSince to use
|
|
706
629
|
:return: list of FhirGetResponse objects
|
|
707
630
|
"""
|
|
708
|
-
def log_running_tasks(prefix: str = "") -> int:
|
|
709
|
-
"""Log currently running asyncio tasks"""
|
|
710
|
-
all_tasks = asyncio.all_tasks()
|
|
711
|
-
running_tasks = [t for t in all_tasks if not t.done()]
|
|
712
|
-
task_count = len(running_tasks)
|
|
713
|
-
waiting_tasks = [t for t in running_tasks if t._coro.cr_await is not None]
|
|
714
|
-
|
|
715
|
-
self._internal_logger.info(
|
|
716
|
-
f"{prefix} | ASYNC TASKS: Total Running={task_count} | "
|
|
717
|
-
f"all_tasks={len(all_tasks)} | waiting_tasks={len(waiting_tasks)}"
|
|
718
|
-
)
|
|
719
|
-
print(f"{prefix} | ASYNC TASKS: Total Running={task_count} | all_tasks={len(all_tasks)} | waiting_tasks={len(waiting_tasks)}")
|
|
720
|
-
|
|
721
|
-
return task_count
|
|
722
|
-
|
|
723
|
-
start_time: datetime = datetime.now()
|
|
724
631
|
children: list[FhirBundleEntry] = []
|
|
725
632
|
child_response: FhirGetResponse
|
|
726
633
|
target_type: str | None = target.type_
|
|
@@ -736,8 +643,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
736
643
|
f"params: {target.params}"
|
|
737
644
|
)
|
|
738
645
|
|
|
739
|
-
log_running_tasks(prefix="[PROCESS_TARGET START]")
|
|
740
|
-
|
|
741
646
|
# forward link and iterate over list
|
|
742
647
|
if path and "[x]" in path and parent_bundle_entries:
|
|
743
648
|
child_ids = []
|
|
@@ -773,7 +678,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
773
678
|
):
|
|
774
679
|
child_ids.append(reference_parts[-2])
|
|
775
680
|
if request_size and len(child_ids) == request_size:
|
|
776
|
-
log_running_tasks(prefix="[BEFORE PROCESS_CHILD_GROUP]")
|
|
777
681
|
child_response = await self._process_child_group(
|
|
778
682
|
resource_type=target_type,
|
|
779
683
|
id_=child_ids,
|
|
@@ -786,13 +690,11 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
786
690
|
id_search_unsupported_resources=id_search_unsupported_resources,
|
|
787
691
|
add_cached_bundles_to_result=add_cached_bundles_to_result,
|
|
788
692
|
)
|
|
789
|
-
log_running_tasks(prefix="[AFTER PROCESS_CHILD_GROUP]")
|
|
790
693
|
yield child_response
|
|
791
694
|
children.extend(child_response.get_bundle_entries())
|
|
792
695
|
child_ids = []
|
|
793
696
|
parent_ids = []
|
|
794
697
|
if child_ids:
|
|
795
|
-
log_running_tasks(prefix="[BEFORE FINAL_PROCESS_CHILD_GROUP]")
|
|
796
698
|
child_response = await self._process_child_group(
|
|
797
699
|
resource_type=target_type,
|
|
798
700
|
id_=child_ids,
|
|
@@ -805,7 +707,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
805
707
|
id_search_unsupported_resources=id_search_unsupported_resources,
|
|
806
708
|
add_cached_bundles_to_result=add_cached_bundles_to_result,
|
|
807
709
|
)
|
|
808
|
-
log_running_tasks(prefix="[AFTER FINAL_PROCESS_CHILD_GROUP]")
|
|
809
710
|
yield child_response
|
|
810
711
|
children.extend(child_response.get_bundle_entries())
|
|
811
712
|
elif path and parent_bundle_entries and target_type:
|
|
@@ -832,7 +733,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
832
733
|
):
|
|
833
734
|
child_ids.append(reference_parts[-2])
|
|
834
735
|
if request_size and len(child_ids) == request_size:
|
|
835
|
-
log_running_tasks(prefix="[BEFORE PROCESS_CHILD_GROUP]")
|
|
836
736
|
child_response = await self._process_child_group(
|
|
837
737
|
resource_type=target_type,
|
|
838
738
|
id_=child_ids,
|
|
@@ -845,13 +745,11 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
845
745
|
id_search_unsupported_resources=id_search_unsupported_resources,
|
|
846
746
|
add_cached_bundles_to_result=add_cached_bundles_to_result,
|
|
847
747
|
)
|
|
848
|
-
log_running_tasks(prefix="[AFTER PROCESS_CHILD_GROUP]")
|
|
849
748
|
yield child_response
|
|
850
749
|
children.extend(child_response.get_bundle_entries())
|
|
851
750
|
child_ids = []
|
|
852
751
|
parent_ids = []
|
|
853
752
|
if child_ids:
|
|
854
|
-
log_running_tasks(prefix="[BEFORE FINAL_PROCESS_CHILD_GROUP]")
|
|
855
753
|
child_response = await self._process_child_group(
|
|
856
754
|
resource_type=target_type,
|
|
857
755
|
id_=child_ids,
|
|
@@ -864,7 +762,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
864
762
|
id_search_unsupported_resources=id_search_unsupported_resources,
|
|
865
763
|
add_cached_bundles_to_result=add_cached_bundles_to_result,
|
|
866
764
|
)
|
|
867
|
-
log_running_tasks(prefix="[AFTER FINAL_PROCESS_CHILD_GROUP]")
|
|
868
765
|
yield child_response
|
|
869
766
|
children.extend(child_response.get_bundle_entries())
|
|
870
767
|
|
|
@@ -901,7 +798,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
901
798
|
parent_ids.append(parent_id)
|
|
902
799
|
if request_size and len(parent_ids) == request_size:
|
|
903
800
|
request_parameters = [f"{property_name}={','.join(parent_ids)}"] + additional_parameters
|
|
904
|
-
log_running_tasks(prefix="[BEFORE PROCESS_CHILD_GROUP]")
|
|
905
801
|
child_response = await self._process_child_group(
|
|
906
802
|
resource_type=target_type,
|
|
907
803
|
parent_ids=parent_ids,
|
|
@@ -914,13 +810,11 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
914
810
|
id_search_unsupported_resources=id_search_unsupported_resources,
|
|
915
811
|
add_cached_bundles_to_result=add_cached_bundles_to_result,
|
|
916
812
|
)
|
|
917
|
-
log_running_tasks(prefix="[AFTER PROCESS_CHILD_GROUP]")
|
|
918
813
|
yield child_response
|
|
919
814
|
children.extend(child_response.get_bundle_entries())
|
|
920
815
|
parent_ids = []
|
|
921
816
|
if parent_ids:
|
|
922
817
|
request_parameters = [f"{property_name}={','.join(parent_ids)}"] + additional_parameters
|
|
923
|
-
log_running_tasks(prefix="[BEFORE FINAL_PROCESS_CHILD_GROUP]")
|
|
924
818
|
child_response = await self._process_child_group(
|
|
925
819
|
resource_type=target_type,
|
|
926
820
|
parent_ids=parent_ids,
|
|
@@ -933,25 +827,11 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
933
827
|
id_search_unsupported_resources=id_search_unsupported_resources,
|
|
934
828
|
add_cached_bundles_to_result=add_cached_bundles_to_result,
|
|
935
829
|
)
|
|
936
|
-
log_running_tasks(prefix="[AFTER FINAL_PROCESS_CHILD_GROUP]")
|
|
937
830
|
yield child_response
|
|
938
831
|
children.extend(child_response.get_bundle_entries())
|
|
939
832
|
if target.link:
|
|
940
833
|
parent_link_map.append((target.link, children))
|
|
941
834
|
|
|
942
|
-
log_running_tasks(prefix="[PROCESS_TARGET END]")
|
|
943
|
-
end_time: datetime = datetime.now()
|
|
944
|
-
if logger:
|
|
945
|
-
logger.debug(
|
|
946
|
-
"Finished Processing target"
|
|
947
|
-
+ f" | target_type: {target_type}"
|
|
948
|
-
+ f" | path: {path}"
|
|
949
|
-
+ f" | start_time: {start_time}"
|
|
950
|
-
+ f" | end_time: {end_time}"
|
|
951
|
-
+ f" | duration: {end_time - start_time}"
|
|
952
|
-
+ f" | resource_count: {len(children)}"
|
|
953
|
-
)
|
|
954
|
-
|
|
955
835
|
async def _get_resources_by_id_one_by_one_async(
|
|
956
836
|
self,
|
|
957
837
|
*,
|
|
@@ -965,7 +845,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
965
845
|
result: FhirGetResponse | None = None
|
|
966
846
|
non_cached_id_list: list[str] = []
|
|
967
847
|
# first check to see if we can find these in the cache
|
|
968
|
-
start_time = datetime.now()
|
|
969
848
|
if ids:
|
|
970
849
|
for resource_id in ids:
|
|
971
850
|
cache_entry: RequestCacheEntry | None = await cache.get_async(
|
|
@@ -1026,17 +905,7 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1026
905
|
)
|
|
1027
906
|
if cache_updated and logger:
|
|
1028
907
|
logger.info(f"Inserted {result2.status} for {resource_type}/{single_id} into cache (1by1)")
|
|
1029
|
-
|
|
1030
|
-
if logger:
|
|
1031
|
-
logger.info(
|
|
1032
|
-
"Completed fetching resources one by one"
|
|
1033
|
-
+ f" | resource_type: {resource_type}"
|
|
1034
|
-
+ f" | ids: {ids}"
|
|
1035
|
-
+ f" | fetched_count: {len(non_cached_id_list)}"
|
|
1036
|
-
+ f" | start_time: {start_time}"
|
|
1037
|
-
+ f" | end_time: {end_time}"
|
|
1038
|
-
+ f" | duration: {end_time - start_time}"
|
|
1039
|
-
)
|
|
908
|
+
|
|
1040
909
|
return result
|
|
1041
910
|
|
|
1042
911
|
async def _get_resources_by_parameters_async(
|
|
@@ -1052,26 +921,7 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1052
921
|
add_cached_bundles_to_result: bool = True,
|
|
1053
922
|
compare_hash: bool = True,
|
|
1054
923
|
) -> tuple[FhirGetResponse, int]:
|
|
1055
|
-
def log_running_tasks(prefix: str = "") -> int:
|
|
1056
|
-
"""Log currently running asyncio tasks"""
|
|
1057
|
-
all_tasks = asyncio.all_tasks()
|
|
1058
|
-
running_tasks = [t for t in all_tasks if not t.done()]
|
|
1059
|
-
task_count = len(running_tasks)
|
|
1060
|
-
waiting_tasks = [t for t in running_tasks if t._coro.cr_await is not None]
|
|
1061
|
-
|
|
1062
|
-
self._internal_logger.info(
|
|
1063
|
-
f"{prefix} | ASYNC TASKS: Total Running={task_count} | "
|
|
1064
|
-
f"all_tasks={len(all_tasks)} | waiting_tasks={len(waiting_tasks)}"
|
|
1065
|
-
)
|
|
1066
|
-
print(f"{prefix} | ASYNC TASKS: Total Running={task_count} | all_tasks={len(all_tasks)} | waiting_tasks={len(waiting_tasks)}")
|
|
1067
|
-
|
|
1068
|
-
return task_count
|
|
1069
|
-
|
|
1070
924
|
assert resource_type
|
|
1071
|
-
|
|
1072
|
-
log_running_tasks(prefix="[GET_RESOURCES_BY_PARAMS START]")
|
|
1073
|
-
|
|
1074
|
-
start_time = datetime.now()
|
|
1075
925
|
if not scope_parser.scope_allows(resource_type=resource_type):
|
|
1076
926
|
if logger:
|
|
1077
927
|
logger.debug(f"Skipping resource {resource_type} due to scope")
|
|
@@ -1122,9 +972,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1122
972
|
non_cached_id_list.append(resource_id)
|
|
1123
973
|
|
|
1124
974
|
all_result: FhirGetResponse | None = None
|
|
1125
|
-
|
|
1126
|
-
log_running_tasks(prefix="[BEFORE HTTP FETCH]")
|
|
1127
|
-
|
|
1128
975
|
# either we have non-cached ids or this is a query without id but has other parameters
|
|
1129
976
|
if (
|
|
1130
977
|
(len(non_cached_id_list) > 1 and resource_type.lower() not in id_search_unsupported_resources)
|
|
@@ -1191,8 +1038,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1191
1038
|
compare_hash=compare_hash,
|
|
1192
1039
|
)
|
|
1193
1040
|
|
|
1194
|
-
log_running_tasks(prefix="[AFTER HTTP FETCH]")
|
|
1195
|
-
|
|
1196
1041
|
# This list tracks the non-cached ids that were found
|
|
1197
1042
|
found_non_cached_id_list: list[str] = []
|
|
1198
1043
|
# Cache the fetched entries
|
|
@@ -1285,20 +1130,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1285
1130
|
storage_mode=self._storage_mode,
|
|
1286
1131
|
)
|
|
1287
1132
|
)
|
|
1288
|
-
|
|
1289
|
-
log_running_tasks(prefix="[GET_RESOURCES_BY_PARAMS END]")
|
|
1290
|
-
|
|
1291
|
-
end_time = datetime.now()
|
|
1292
|
-
if logger:
|
|
1293
|
-
logger.info(
|
|
1294
|
-
"Completed fetching resources by parameters"
|
|
1295
|
-
+ f" | resource_type: {resource_type}"
|
|
1296
|
-
+ f" | ids: {id_}"
|
|
1297
|
-
+ f" | fetched_count: {len(found_non_cached_id_list)}"
|
|
1298
|
-
+ f" | start_time: {start_time}"
|
|
1299
|
-
+ f" | end_time: {end_time}"
|
|
1300
|
-
+ f" | duration: {end_time - start_time}"
|
|
1301
|
-
)
|
|
1302
1133
|
return bundle_response, cache.cache_hits
|
|
1303
1134
|
|
|
1304
1135
|
# noinspection PyPep8Naming
|
|
File without changes
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
class FhirClientSdkOpenTelemetryAttributeNames:
|
|
2
|
+
"""Constants for OpenTelemetry attribute names used in the FHIR Client SDK."""
|
|
3
|
+
|
|
4
|
+
URL: str = "fhir.client_sdk.url"
|
|
5
|
+
RESOURCE: str = "fhir.client_sdk.resource"
|
|
6
|
+
JSON_DATA_COUNT: str = "fhir.client_sdk.json_data.count"
|
|
7
|
+
BATCH_SIZE: str = "fhir.client_sdk.batch.size"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class FhirClientSdkOpenTelemetrySpanNames:
|
|
2
|
+
"""Span names for OpenTelemetry tracing in the FHIR Client SDK."""
|
|
3
|
+
|
|
4
|
+
GET: str = "fhir.client_sdk.get"
|
|
5
|
+
GET_STREAMING: str = "fhir.client_sdk.streaming.get"
|
|
6
|
+
GET_ACCESS_TOKEN: str = "fhir.client_sdk.access_token.get"
|
|
7
|
+
HTTP_GET: str = "fhir.client_sdk.http.get"
|
|
8
|
+
HANDLE_RESPONSE: str = "fhir.client_sdk.handle_response"
|
|
9
|
+
DELETE: str = "fhir.client_sdk.delete"
|
|
10
|
+
UPDATE: str = "fhir.client_sdk.update"
|
|
11
|
+
PATCH: str = "fhir.client_sdk.patch"
|
|
12
|
+
MERGE: str = "fhir.client_sdk.merge"
|