@@ -204,9 +204,12 @@ class IbisSignature(NamedTuple):
204
204
output_type : IbisDataType
205
205
206
206
207
- def get_cloud_function_name (function_hash , session_id , uniq_suffix = None ):
207
+ def get_cloud_function_name (function_hash , session_id = None , uniq_suffix = None ):
208
208
"Get a name for the cloud function for the given user defined function."
209
- parts = [_BIGFRAMES_REMOTE_FUNCTION_PREFIX , session_id , function_hash ]
209
+ parts = [_BIGFRAMES_REMOTE_FUNCTION_PREFIX ]
210
+ if session_id :
211
+ parts .append (session_id )
212
+ parts .append (function_hash )
210
213
if uniq_suffix :
211
214
parts .append (uniq_suffix )
212
215
return _GCF_FUNCTION_NAME_SEPERATOR .join (parts )
@@ -566,10 +569,13 @@ def provision_bq_remote_function(
566
569
)
567
570
568
571
# Derive the name of the cloud function underlying the intended BQ
569
- # remote function, also collect updated package requirements as
570
- # determined in the name resolution
572
+ # remote function. Use the session id to identify the GCF for unnamed
573
+ # functions. The named remote functions are treated as a persistant
574
+ # artifacts, so let's keep them independent of session id, which also
575
+ # makes their naming more stable for the same udf code
576
+ session_id = None if name else self ._session .session_id
571
577
cloud_function_name = get_cloud_function_name (
572
- function_hash , self . _session . session_id , uniq_suffix
578
+ function_hash , session_id , uniq_suffix
573
579
)
574
580
cf_endpoint = self .get_cloud_function_endpoint (cloud_function_name )
575
581
@@ -635,13 +641,12 @@ def get_remote_function_specs(self, remote_function_name):
635
641
)
636
642
try :
637
643
for routine in routines :
644
+ routine = cast (bigquery .Routine , routine )
638
645
if routine .reference .routine_id == remote_function_name :
639
- # TODO(shobs): Use first class properties when they are available
640
- # https://github.com/googleapis/python-bigquery/issues/1552
641
- rf_options = routine ._properties .get ("remoteFunctionOptions" )
646
+ rf_options = routine .remote_function_options
642
647
if rf_options :
643
- http_endpoint = rf_options .get ( " endpoint" )
644
- bq_connection = rf_options .get ( " connection" )
648
+ http_endpoint = rf_options .endpoint
649
+ bq_connection = rf_options .connection
645
650
if bq_connection :
646
651
bq_connection = os .path .basename (bq_connection )
647
652
break
@@ -731,15 +736,15 @@ class _RemoteFunctionSession:
731
736
732
737
def __init__ (self ):
733
738
# Session level mapping of remote function artifacts
734
- self ._temp_session_artifacts : Dict [str , str ] = dict ()
739
+ self ._temp_artifacts : Dict [str , str ] = dict ()
735
740
736
- # Lock to synchronize the update of the session level mapping
737
- self ._session_artifacts_lock = threading .Lock ()
741
+ # Lock to synchronize the update of the session artifacts
742
+ self ._artifacts_lock = threading .Lock ()
738
743
739
- def _update_artifacts (self , bqrf_routine : str , gcf_path : str ):
744
+ def _update_temp_artifacts (self , bqrf_routine : str , gcf_path : str ):
740
745
"""Update remote function artifacts in the current session."""
741
- with self ._session_artifacts_lock :
742
- self ._temp_session_artifacts [bqrf_routine ] = gcf_path
746
+ with self ._artifacts_lock :
747
+ self ._temp_artifacts [bqrf_routine ] = gcf_path
743
748
744
749
def clean_up (
745
750
self ,
@@ -748,8 +753,8 @@ def clean_up(
748
753
session_id : str ,
749
754
):
750
755
"""Delete remote function artifacts in the current session."""
751
- with self ._session_artifacts_lock :
752
- for bqrf_routine , gcf_path in self ._temp_session_artifacts .items ():
756
+ with self ._artifacts_lock :
757
+ for bqrf_routine , gcf_path in self ._temp_artifacts .items ():
753
758
# Let's accept the possibility that the remote function may have
754
759
# been deleted directly by the user
755
760
bqclient .delete_routine (bqrf_routine , not_found_ok = True )
@@ -761,7 +766,7 @@ def clean_up(
761
766
except google .api_core .exceptions .NotFound :
762
767
pass
763
768
764
- self ._temp_session_artifacts .clear ()
769
+ self ._temp_artifacts .clear ()
765
770
766
771
# Inspired by @udf decorator implemented in ibis-bigquery package
767
772
# https://github.com/ibis-project/ibis-bigquery/blob/main/ibis_bigquery/udf/__init__.py
@@ -1206,7 +1211,7 @@ def try_delattr(attr):
1206
1211
# explicit name, we are assuming that the user wants to persist them
1207
1212
# with that name and would directly manage their lifecycle.
1208
1213
if created_new and (not name ):
1209
- self ._update_artifacts (
1214
+ self ._update_temp_artifacts (
1210
1215
func .bigframes_remote_function , func .bigframes_cloud_function
1211
1216
)
1212
1217
return func
0 commit comments