2626# Ask once whether to pause between steps during this run
2727pause_choice = input ("Pause between test steps? (y/N): " ).strip () or "n"
2828pause_between_steps = (str (pause_choice ).lower () in ("y" , "yes" , "true" , "1" ))
29+ instant_create_choice = input ("Run instant create demo? (y/N): " ).strip () or "n"
30+ run_instant_create = (str (instant_create_choice ).lower () in ("y" , "yes" , "true" , "1" ))
2931# Create a credential we can reuse (for DataverseClient)
3032credential = InteractiveBrowserCredential ()
3133client = DataverseClient (base_url = base_url , credential = credential )
@@ -42,6 +44,20 @@ def pause(next_step: str) -> None:
4244 # If stdin is not available, just proceed
4345 pass
4446
47+ # Helper: delete a table if it exists
48+ def delete_table_if_exists (table_name : str ) -> None :
49+ try :
50+ log_call (f"client.get_table_info('{ table_name } ')" )
51+ info = client .get_table_info (table_name )
52+ if info :
53+ log_call (f"client.delete_table('{ table_name } ')" )
54+ client .delete_table (table_name )
55+ print ({"table_deleted" : True })
56+ else :
57+ print ({"table_deleted" : False , "reason" : "not found" })
58+ except Exception as e :
59+ print ({f"Delete table failed" : str (e )})
60+
4561# Small generic backoff helper used only in this quickstart
4662# Include common transient statuses like 429/5xx to improve resilience.
4763def backoff_retry (op , * , delays = (0 , 2 , 5 , 10 , 20 ), retry_http_statuses = (400 , 403 , 404 , 409 , 412 , 429 , 500 , 502 , 503 , 504 ), retry_if = None ):
@@ -68,6 +84,11 @@ def backoff_retry(op, *, delays=(0, 2, 5, 10, 20), retry_http_statuses=(400, 403
6884table_info = None
6985created_this_run = False
7086
87+ # Timing metrics for comparison (seconds)
88+ instant_create_seconds : float | None = None
89+ standard_create_seconds : float | None = None
90+ warm_up_seconds : float | None = None
91+
7192# Check for existing table using list_tables
7293log_call ("client.list_tables()" )
7394tables = client .list_tables ()
@@ -87,6 +108,7 @@ def backoff_retry(op, *, delays=(0, 2, 5, 10, 20), retry_http_statuses=(400, 403
87108 # Create it since it doesn't exist
88109 try :
89110 log_call ("client.create_table('new_SampleItem', schema={code,count,amount,when,active})" )
111+ _t0_standard = time .perf_counter ()
90112 table_info = client .create_table (
91113 "new_SampleItem" ,
92114 {
@@ -97,6 +119,7 @@ def backoff_retry(op, *, delays=(0, 2, 5, 10, 20), retry_http_statuses=(400, 403
97119 "active" : "bool" ,
98120 },
99121 )
122+ standard_create_seconds = time .perf_counter () - _t0_standard
100123 created_this_run = True if table_info and table_info .get ("columns_created" ) else False
101124 print ({
102125 "table" : table_info .get ("entity_schema" ) if table_info else None ,
@@ -124,6 +147,19 @@ def backoff_retry(op, *, delays=(0, 2, 5, 10, 20), retry_http_statuses=(400, 403
124147entity_set = table_info .get ("entity_set_name" )
125148logical = table_info .get ("entity_logical_name" ) or entity_set .rstrip ("s" )
126149
150+ if run_instant_create :
151+ # call early to warm up for instant create
152+ log_call ("client.warm_up_instant_create()" )
153+ try :
154+ _t0_warm = time .perf_counter ()
155+ client .warm_up_instant_create ()
156+ warm_up_seconds = time .perf_counter () - _t0_warm
157+ print ({"warm_up_for_instant_create" : True , "warm_up_seconds" : warm_up_seconds })
158+ except Exception as warm_ex :
159+ print ({"warm_up_for_instant_create_error" : str (warm_ex )})
160+ # Abort instant demo if warm-up fails
161+ sys .exit (1 )
162+
127163# Derive attribute logical name prefix from the entity logical name (segment before first underscore)
128164attr_prefix = logical .split ("_" , 1 )[0 ] if "_" in logical else logical
129165code_key = f"{ attr_prefix } _code"
@@ -410,21 +446,77 @@ def _del_one(rid: str) -> tuple[str, bool, str | None]:
410446except Exception as e :
411447 print (f"Delete failed: { e } " )
412448
449+ # 6) (Optional) Instant create path demo
450+ if not run_instant_create :
451+ print ("Skipping instant create demo as per user choice." )
452+ else :
453+ pause ("Next: instant create demo" )
454+
455+ print ("Instant create demo" )
456+ print ("Delete Instant table first if exists" )
457+ # Delete instant table first
458+ delete_table_if_exists ("new_SampleItemInstant" )
459+
460+ # Create Instant
461+ log_call ("client.create_table('new_SampleItemInstant', instant_create)" )
462+ instant_schema = {
463+ "code" : "text" ,
464+ "count" : "text" ,
465+ }
466+ # Demo dummy lookup definition (must supply at least one for instant path)
467+ instant_lookups = [
468+ {
469+ "AttributeName" : "new_Account" ,
470+ "AttributeDisplayName" : "Account (Demo Lookup)" ,
471+ "ReferencedEntityName" : "account" ,
472+ "RelationshipName" : "new_newSampleItem_account" ,
473+ }
474+ ]
475+ try :
476+ _t0_instant = time .perf_counter ()
477+ _table_instant = client .create_table (
478+ "new_SampleItemInstant" ,
479+ instant_schema ,
480+ use_instant = True ,
481+ display_name = "Sample Item" ,
482+ lookups = instant_lookups ,
483+ )
484+ instant_create_seconds = time .perf_counter () - _t0_instant
485+ table_info = _table_instant
486+ logical = table_info .get ("entity_logical_name" ) if isinstance (table_info , dict ) else None
487+ print (table_info )
488+ except Exception as instant_ex :
489+ print ({"instant_create_error" : str (instant_ex )})
490+ sys .exit (1 )
491+
492+ # Timing comparison summary for table creation
493+ _standard_create_ran = standard_create_seconds is not None
494+ _instant_create_ran = instant_create_seconds is not None
495+ print ({
496+ "table_creation_timing_compare" : {
497+ "warm_up_seconds" : warm_up_seconds ,
498+ "instant_seconds" : instant_create_seconds ,
499+ "warm_up+instant_seconds" : warm_up_seconds + instant_create_seconds ,
500+ "standard_seconds" : standard_create_seconds if _standard_create_ran else "standard table pre-existed; omitted" ,
501+ "delta_standard_minus_instant" : (
502+ (standard_create_seconds - instant_create_seconds )
503+ if (_standard_create_ran and _instant_create_ran )
504+ else None
505+ ),
506+ }
507+ })
508+
509+
413510pause ("Next: Cleanup table" )
414511
415- # 6 ) Cleanup: delete the custom table if it exists
512+ # 7 ) Cleanup: delete the custom table if it exists
416513print ("Cleanup (Metadata):" )
417514if delete_table_at_end :
418- try :
419- log_call ("client.get_table_info('new_SampleItem')" )
420- info = client .get_table_info ("new_SampleItem" )
421- if info :
422- log_call ("client.delete_table('new_SampleItem')" )
423- client .delete_table ("new_SampleItem" )
424- print ({"table_deleted" : True })
425- else :
426- print ({"table_deleted" : False , "reason" : "not found" })
427- except Exception as e :
428- print (f"Delete table failed: { e } " )
515+ delete_table_if_exists ("new_SampleItem" )
429516else :
430517 print ({"table_deleted" : False , "reason" : "user opted to keep table" })
518+
519+ # Put instant table delete at the end to avoid metadata cache issues when deletion immediately follows creation
520+ if run_instant_create :
521+ print ("Cleanup instant (Metadata):" )
522+ delete_table_if_exists ("new_SampleItemInstant" )
0 commit comments