szymon_dybczak
Esteemed Contributor III

Hi @Debasis_Pal ,

The current Power BI task that is available in databricks workflow will wait for refresh process to return correct status (whether it succeeded or failed).

If you need to replicate the same behaviour as in ADF you can start refresh process by using asynchronous REST API call. The refresh process will start and your cluster can be terminated after that. I'm using this approach in one of the client I worked with.

https://learn.microsoft.com/en-us/power-bi/connect-data/asynchronous-refresh

 

import time
import requests
from azure.identity import ClientSecretCredential


_AUTHORITY = "https://login.microsoftonline.com/"
_PBI_SCOPE = "https://analysis.windows.net/powerbi/api/.default"
_REFRESHES_URL = "https://api.powerbi.com/v1.0/myorg/groups/{workspace_id}/datasets/{dataset_id}/refreshes"

_TERMINAL_STATUSES = {"Completed", "Failed", "Disabled"}
_POLL_INTERVAL_SECONDS = 120


class PowerBIRefreshError(Exception):
    pass


def _get_credential(dbutils, secret_scope, tenant_key, client_id_key, client_secret_key):
    return ClientSecretCredential(
        authority=_AUTHORITY,
        tenant_id=dbutils.secrets.get(scope=secret_scope, key=tenant_key),
        client_id=dbutils.secrets.get(scope=secret_scope, key=client_id_key),
        client_secret=dbutils.secrets.get(scope=secret_scope, key=client_secret_key),
    )


def _auth_headers(credential):
    token = credential.get_token(_PBI_SCOPE).token
    return {"Authorization": f"Bearer {token}"}


def _get_latest_refresh_status(url, credential):
    response = requests.get(url, headers=_auth_headers(credential))
    response.raise_for_status()

    refreshes = response.json().get("value", [])
    return refreshes[0]["status"] if refreshes else None


def _raise_for_pbi_status(response):
    messages = {
        400: "Bad Request: missing or malformed parameters.",
        401: "Unauthorized: authentication failed or insufficient permissions.",
        403: "Forbidden: authenticated user lacks access to the resource.",
        404: "Not Found: the requested resource does not exist.",
        500: "Internal Server Error: an error occurred on the Power BI service.",
    }
    message = messages.get(response.status_code)
    if message:
        raise PowerBIRefreshError(message)
    response.raise_for_status()


def refresh_power_bi_model(
    dbutils,
    secret_scope,
    secret_tenant_key,
    secret_client_id_key,
    secret_client_secret_key,
    workspace_id,
    dataset_id,
    apply_refresh_policy,
    commit_mode,
    poll_interval=_POLL_INTERVAL_SECONDS,
):
    """
    Triggers a Power BI dataset refresh and polls until it reaches a terminal state.

    Returns the terminal status string: "Completed", "Failed", or "Disabled".
    Raises PowerBIRefreshError on API errors or if a refresh is already in progress.
    """
    url = _REFRESHES_URL.format(workspace_id=workspace_id, dataset_id=dataset_id)
    credential = _get_credential(
        dbutils, secret_scope, secret_tenant_key, secret_client_id_key, secret_client_secret_key
    )

    if _get_latest_refresh_status(url, credential) == "InProgress":
        raise PowerBIRefreshError("Dataset is already refreshing. Cannot start a new refresh.")

    payload = {
        "type": "full",
        "commitMode": commit_mode,
        "maxParallelism": 6,
        "retryCount": 0,
        "applyRefreshPolicy": apply_refresh_policy,
    }
    response = requests.post(url, headers=_auth_headers(credential), json=payload)

    if not response.ok:
        _raise_for_pbi_status(response)

    while True:
        status = _get_latest_refresh_status(url, credential)
        if status in _TERMINAL_STATUSES:
            return status
        time.sleep(poll_interval)

 

If my answer was helpful, please consider marking it as accepted solution.

View solution in original post