33import typing as t
44import logging
55import requests
6+ import time
67from functools import cached_property
78from sqlglot import exp
89from tenacity import retry , stop_after_attempt , wait_exponential , retry_if_result
1516from sqlmesh .utils .errors import SQLMeshError
1617from sqlmesh .utils .connection_pool import ConnectionPool
1718
19+
1820if t .TYPE_CHECKING :
1921 from sqlmesh .core ._typing import TableName
2022
@@ -172,8 +174,15 @@ def __init__(self, tenant_id: str, workspace_id: str, client_id: str, client_sec
172174 self .client_secret = client_secret
173175 self .workspace_id = workspace_id
174176
175- def create_warehouse (self , warehouse_name : str , if_not_exists : bool = True ) -> None :
177+ def create_warehouse (
178+ self , warehouse_name : str , if_not_exists : bool = True , attempt : int = 0
179+ ) -> None :
176180 """Create a catalog (warehouse) in Microsoft Fabric via REST API."""
181+
182+ # attempt count is arbitrary, it essentially equates to 30 seconds max wait with the time.sleep() below
183+ if attempt > 3 :
184+ raise SQLMeshError ("Gave up waiting for warehouse to become available" )
185+
177186 logger .info (f"Creating Fabric warehouse: { warehouse_name } " )
178187
179188 request_data = {
@@ -186,12 +195,28 @@ def create_warehouse(self, warehouse_name: str, if_not_exists: bool = True) -> N
186195 if (
187196 if_not_exists
188197 and response .status_code == 400
189- and response .json ().get ("errorCode" , None ) == "ItemDisplayNameAlreadyInUse"
198+ and ( errorCode := response .json ().get ("errorCode" , None ))
190199 ):
191- logger .warning (f"Fabric warehouse { warehouse_name } already exists" )
192- return
193-
194- response .raise_for_status ()
200+ if errorCode == "ItemDisplayNameAlreadyInUse" :
201+ logger .warning (f"Fabric warehouse { warehouse_name } already exists" )
202+ return
203+ if errorCode == "ItemDisplayNameNotAvailableYet" :
204+ logger .warning (f"Fabric warehouse { warehouse_name } is still spinning up; waiting" )
205+ time .sleep (
206+ 10
207+ ) # arbitrary, seems to be "good enough" at least in CI. I was unable to find any guidance in the MS docs on how to handle this case
208+ return self .create_warehouse (
209+ warehouse_name = warehouse_name , if_not_exists = if_not_exists , attempt = attempt + 1
210+ )
211+
212+ try :
213+ response .raise_for_status ()
214+ except :
215+ # the important information to actually debug anything is in the response body which Requests never prints
216+ logger .exception (
217+ f"Failed to create warehouse { warehouse_name } . status: { response .status_code } , body: { response .text } "
218+ )
219+ raise
195220
196221 # Handle direct success (201) or async creation (202)
197222 if response .status_code == 201 :
0 commit comments