Forum Discussion

JibinSebastian's avatar
JibinSebastian
Advocate II
6 months ago
Solved

Mirrored Sql server not Resumeing automatically even after the Capacity resumes

I have connected a mirrored SQL database and everything was working properly. However, our Fabric capacity is scheduled to be suspended at 7:00 PM and resumed the next day at 7:00 AM. Because of this, I need to manually resume the replication in the mirrored SQL database each morning. Is there a way to automate or avoid this manual step?

 

 

  • deborshi_nag's avatar
    deborshi_nag
    6 months ago

    Hello JibinSebastian this is a code snippet you may want to try and see if it works! It restarts any mirrored database in your workspace that is not in Running status. 

     

    def get_fabric_token_via_user() -> str:
        """
        User-context token in a Fabric notebook.
        NOTE: Some endpoints may fail with InsufficientScopes under SPN contexts; SPN is recommended.
        """
        # Try Fabric audience first; fall back to built-in 'pbi' token if needed.
        try:
            return mssparkutils.credentials.getToken("https://api.fabric.microsoft.com/.default")
        except Exception:
            return mssparkutils.credentials.getToken("pbi")
    
    def fabric_request(method: str, path: str, token: str, body: Optional[dict] = None):
        base = "https://api.fabric.microsoft.com/v1"
        url  = path if path.startswith("http") else f"{base}/{path}"
        headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json", "Accept":"application/json"}
    
        # simple 429 retry loop
        for attempt in range(6):
            resp = requests.request(method, url, headers=headers, json=body, timeout=60)
            if resp.status_code != 429:
                if not resp.ok:
                    raise RuntimeError(f"Fabric API {method} {url} failed: {resp.status_code} {resp.text}")
                return resp
            retry_after = int(resp.headers.get("Retry-After", "5"))
            print(f"429 from Fabric API. Retrying in {retry_after}s ...")
            time.sleep(retry_after)
        raise RuntimeError("Fabric API throttled repeatedly (429)")
    
    fabric_token = get_fabric_token_via_user()
    
    def start_mirroring_for_workspace(workspace_id: str):
        print(f"\nWorkspace {workspace_id}: listing mirrored databases ...")
        # GET /workspaces/{workspaceId}/mirroredDatabases
        mirrors = fabric_request("GET", f"workspaces/{workspace_id}/mirroredDatabases", fabric_token).json().get("value", [])
        if not mirrors:
            print("No Mirrored Databases found.")
            return
    
        for m in mirrors:
            mid   = m["id"]
            name  = m.get("displayName", mid)
            # POST /getMirroringStatus
            status = fabric_request("POST", f"workspaces/{workspace_id}/mirroredDatabases/{mid}/getMirroringStatus", fabric_token).json().get("status")
            print(f"  - '{name}': current status = {status}")
            if status != "Running":
                print(f"    Starting mirroring for '{name}' ...")
                # POST /startMirroring
                fabric_request("POST", f"workspaces/{workspace_id}/mirroredDatabases/{mid}/startMirroring", fabric_token)
                time.sleep(2)
                status2 = fabric_request("POST", f"workspaces/{workspace_id}/mirroredDatabases/{mid}/getMirroringStatus", fabric_token).json().get("status")
                print(f"    New status = {status2}")
            else:
                print(f"    Already Running. Skipping.")
    
    for wsid in WORKSPACE_IDS:
        start_mirroring_for_workspace(wsid)
    
    print("\nDone.")

     

4 Replies

  • Hello JibinSebastian 

     

    When a Fabric capacity is resumed following its nightly pause, please note that Mirroring does not automatically resume; the mirrored database will display Status = Paused and requires a Resume replication action to restart change capture.

     

    Below are two Microsoft-native solutions to help eliminate the need for this daily manual intervention.

     

    Time-based resume using Azure Automation
    Mirroring can be managed programmatically (start/stop) via the public REST API. After resuming capacity, invoking Start Mirroring will transition each mirrored database from Paused to Running without the need for manual input in the UI. You can set it to start at a particualr time of the day, say 8 AM in the morning. 

     

    Event-driven resume on “Capacity Resumed”
    Leverage Azure Monitor to listen for the “Resume the specified Fabric capacity” platform event, and trigger an Automation Runbook that initiates Start Mirroring for all mirrored databases associated with that capacity.

     

    For further details, please refer to the official Microsoft documentation:

    Pause and resume your capacity - Microsoft Fabric | Microsoft Learn

     

    • JibinSebastian's avatar
      JibinSebastian
      Advocate II

      Thanks deborshi_nag , I tried creating a fabric notebook to change the status to Running but it didn't worked.

      There was no item for this replication status.

      i will try using Azure automation and will let you know the updates

      thanks again

       

      • deborshi_nag's avatar
        deborshi_nag
        Super User

        Hello JibinSebastian this is a code snippet you may want to try and see if it works! It restarts any mirrored database in your workspace that is not in Running status. 

         

        def get_fabric_token_via_user() -> str:
            """
            User-context token in a Fabric notebook.
            NOTE: Some endpoints may fail with InsufficientScopes under SPN contexts; SPN is recommended.
            """
            # Try Fabric audience first; fall back to built-in 'pbi' token if needed.
            try:
                return mssparkutils.credentials.getToken("https://api.fabric.microsoft.com/.default")
            except Exception:
                return mssparkutils.credentials.getToken("pbi")
        
        def fabric_request(method: str, path: str, token: str, body: Optional[dict] = None):
            base = "https://api.fabric.microsoft.com/v1"
            url  = path if path.startswith("http") else f"{base}/{path}"
            headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json", "Accept":"application/json"}
        
            # simple 429 retry loop
            for attempt in range(6):
                resp = requests.request(method, url, headers=headers, json=body, timeout=60)
                if resp.status_code != 429:
                    if not resp.ok:
                        raise RuntimeError(f"Fabric API {method} {url} failed: {resp.status_code} {resp.text}")
                    return resp
                retry_after = int(resp.headers.get("Retry-After", "5"))
                print(f"429 from Fabric API. Retrying in {retry_after}s ...")
                time.sleep(retry_after)
            raise RuntimeError("Fabric API throttled repeatedly (429)")
        
        fabric_token = get_fabric_token_via_user()
        
        def start_mirroring_for_workspace(workspace_id: str):
            print(f"\nWorkspace {workspace_id}: listing mirrored databases ...")
            # GET /workspaces/{workspaceId}/mirroredDatabases
            mirrors = fabric_request("GET", f"workspaces/{workspace_id}/mirroredDatabases", fabric_token).json().get("value", [])
            if not mirrors:
                print("No Mirrored Databases found.")
                return
        
            for m in mirrors:
                mid   = m["id"]
                name  = m.get("displayName", mid)
                # POST /getMirroringStatus
                status = fabric_request("POST", f"workspaces/{workspace_id}/mirroredDatabases/{mid}/getMirroringStatus", fabric_token).json().get("status")
                print(f"  - '{name}': current status = {status}")
                if status != "Running":
                    print(f"    Starting mirroring for '{name}' ...")
                    # POST /startMirroring
                    fabric_request("POST", f"workspaces/{workspace_id}/mirroredDatabases/{mid}/startMirroring", fabric_token)
                    time.sleep(2)
                    status2 = fabric_request("POST", f"workspaces/{workspace_id}/mirroredDatabases/{mid}/getMirroringStatus", fabric_token).json().get("status")
                    print(f"    New status = {status2}")
                else:
                    print(f"    Already Running. Skipping.")
        
        for wsid in WORKSPACE_IDS:
            start_mirroring_for_workspace(wsid)
        
        print("\nDone.")