Execution engine

Elements: documentatiehub

Elements zijn Python bouwblokken binnen Dashview. Deze hub splitst de documentatie in twee detailreferenties: editor/filebeheer en runtime/execution.

1. End-to-end workflow

  1. Maak element aan met ID, naam, kind en entrypoint.
  2. Voeg code/files toe en stel requirements/pythonVersion in.
  3. Save draft en publiceer een nieuwe version.
  4. Configureer runtime vars/secrets.
  5. Gebruik Test execute en controleer execution logs.
  6. Koppel element aan datasource connector of Autoflow nodes.
Elements overzicht
  • De lijst is het centrale beheerpunt voor publiceren, uitvoeren, versies en logs.
  • Gebruik het overzicht om snel te zien welke Elements actief worden onderhouden.
  • Open van hieruit alleen de Elements die je echt wilt wijzigen of testen.
Hier beheer je de volledige lifecycle van tenant-specifieke Pythoncode.
Element detail
  • Binnen één Element beheer je basisvelden, bestanden, requirements en runtime-instellingen.
  • De editor ondersteunt meer dan alleen main.py; splits modules zodra logica groeit.
  • Publiceer pas nadat execute en logs laten zien dat de runtime klopt.
Een stabiel Element bestaat uit code, dependencybeheer en een gecontroleerde publishflow.

2. Detailreferenties

Runtime & execution reference

Publish/versioning, runtime vars/secrets, test execute payloads en logvelden.

Open runtime reference →

3. Integratie met datasources en flows

4. Quick start: Element naar dashboardwidget

Basisroute

  1. Maak een Element dat rows teruggeeft met def run(params):.
  2. Test het Element met een kleine params-payload en publiceer daarna een versie.
  3. Maak een datasource met type element en kies het gepubliceerde Element.
  4. Vul vaste input in via elementParams, bijvoorbeeld een default country of limit.
  5. Refresh of test de datasource zodat kolommen en voorbeeldrows zichtbaar zijn.
  6. Koppel een tabel-, chart- of KPI-widget aan die datasource en gebruik de returned columns zoals bij elke andere datasource.

Hoe filters terug naar het Element gaan

  • Dashboardfilters en form-widget velden worden eerst runtime filterwaarden op de pagina.
  • Een Element-datasource kan die waarden als request params ontvangen wanneer request-param forwarding aan staat.
  • Gebruik allowedRequestParams om expliciet te bepalen welke filterkeys naar het Element mogen.
  • Gebruik requestParamMap als de dashboardfilter anders heet dan de param die je Element verwacht.
  • In het Element lees je ze gewoon uit params, bijvoorbeeld params.get("country").

Mini-voorbeeld met filterinput

def run(params):
    country = params.get("country", "NL")
    limit = int(params.get("limit", 10))

    rows = load_sales_rows(country=country, limit=limit)
    return [{
        "country": row["country"],
        "customer": row["customer"],
        "revenue": row["revenue"],
    } for row in rows]

Voorbeeldflow: dashboardfilter country → Element-datasource request param countryparams.get("country") in het Element → widget rendert de nieuwe rows.

Houd filterdoorvoer expliciet. Gebruik allowlists en hernoem alleen bewust, zodat widgets geen onverwachte params naar Elements sturen.

5. Element contract voor datasource transforms

Input in params

  • params.rows: inputdataset van de huidige transformstap.
  • params.transformParams: transformconfig uit de datasource.
  • context: tenant/element/version metadata.

Return value

  • Return altijd een lijst met rows (array van objecten).
  • Gebruik yield alleen als het Element rows incrementeel produceert; mix dat niet met een return value.
  • Vermijd tuple-output als eindresultaat; connector verwacht rows.
  • Als een interne helper (rows, info) teruggeeft, return je alleen rows.

Voorbeeld transform-wrapper

def run(params):
    rows = params.get("rows") or []
    transform_params = params.get("transformParams") or {}

    result = predict_session_pattern_trend(rows, transform_params)
    if isinstance(result, tuple) and len(result) == 2:
      return result[0]  # alleen rows teruggeven
    return result

6. Datasource queries vanuit een Element

queryDataSources

  • Gebruik de ingebouwde datasource-helper wanneer een Element tenant-datasource data moet lezen.
  • Gebruik in SQL standaard tabelnamen met global_<dataSourceId>.
  • Niet-alfanumerieke tekens worden underscores: datasource orders-prod wordt global_orders_prod.
  • Gebruik alleen een afwijkende tabelnaam wanneer de datasource expliciet een tableName override heeft.

Voorbeeld

def run(params):
    result = queryDataSources("""
        select customer, revenue
        from global_orders
        order by revenue desc
        limit 100
    """)
    return result["rows"]
Weet je de exacte datasource-ID of kolommen niet zeker, controleer eerst de datasource schema's in de admin in plaats van te gokken.

7. Return, yield en memorygebruik

return: standaard output

  • Gebruik return rows voor normale Elements, transforms en kleine tot middelgrote snapshots.
  • De return value moet JSON-serialiseerbaar zijn. Voor datasource transforms is dat normaal een lijst met dicts.
  • Return geen wrapper zoals {"rows": rows, "meta": ...} als de downstream datasource een pure rows-array verwacht.

yield: rows stuk voor stuk produceren

  • Gebruik yield row wanneer je rows kunt produceren zonder eerst alles in een lijst te verzamelen.
  • Een generator-resultaat wordt door de runner als streambare row-output behandeld en naar een tijdelijk row-artifact geschreven.
  • Gebruik in dezelfde entrypoint niet tegelijk yield en return rows; kies één outputmodus.

Memoryrichtlijnen voor grote datasets

  • Vermijd patronen zoals rows = list(iterator) als de bron groot kan worden. Je laadt dan de volledige dataset in het geheugen van de Element-runner.
  • Filter, map en aggregeer per row of per kleine batch wanneer dat kan, en yield daarna de outputrow.
  • Gebruik queryDataSources(..., maxRows=...) of datasourcefilters om de input bewust te begrenzen wanneer je alleen een sample of top-N nodig hebt.
  • Gebruik .to_pandas() alleen als je echt een DataFrame nodig hebt; die stap materialiseert alle opgehaalde rows opnieuw in memory.
  • Voor live datasource updates gebruik je appendRows, replaceRows en emitProgress; yield is voor het eindresultaat van de entrypoint, niet voor progress-events.

Vermijd volledige materialisatie

def run(params):
    # Minder goed: alle rows eerst in memory verzamelen.
    rows = list(load_external_rows(params))
    return [normalize(row) for row in rows]

Produceer rows incrementeel

def run(params):
    # Beter voor grote bronnen: per row verwerken.
    for row in load_external_rows(params):
        yield normalize(row)

8. Code voorbeelden

Voorbeeld A: run(params)

def run(params):
    limit = int(params.get("limit", 5))
    country = params.get("country", "NL")
    rows = []
    for i in range(limit):
        rows.append({
            "rank": i + 1,
            "country": country,
            "value": (i + 1) * 100
        })
    return rows

Voorbeeld B: parameters verwerken

def run(params):
    label = params.get("label", "demo")
    multiplier = int(params.get("multiplier", 2))
    values = params.get("values") or [1, 2, 3]
    return [{
        "label": label,
        "value": value,
        "score": value * multiplier
    } for value in values]

Voorbeeld C: runtime variabele gebruiken

def run(params):
    cursor = int(getVar("sync_cursor", 0) or 0)
    batch_size = int(params.get("batchSize", 3))
    rows = []
    for index in range(batch_size):
        rows.append({"cursor": cursor + index, "source": "element"})
    setVar("sync_cursor", cursor + batch_size)
    return rows