Hoe ik Teams niet maak (en ze toch ontstaan)
Het probleem is niet Teams maken
We wilden Teams voor lessen.
Dat klinkt simpel:
- lees brondata
- maak teams
- voeg docenten en leerlingen toe
- klaar
Maar in de praktijk werkt dat niet.
Want:
- lessen zijn niet altijd volledig gepland
- teams mogen niet direct zichtbaar zijn
- Microsoft Graph is asynchroon
- resources bestaan vaak nog niet of zijn niet klaar
Het echte probleem bleek niet te zijn:
“Hoe maak ik Teams?”
Maar:
“Hoe voorkom ik dat Teams te vroeg actief worden?”
Waarom standaard Teams niet werken
Als je een Team direct aanmaakt via de standaard Microsoft flows:
→ Team bestaat
→ Team is actief
→ gebruikers kunnen ermee werken
Voor onderwijs is dat ongewenst.
Een Team moet pas gebruikt worden als:
- de docent er klaar voor is
- de les daadwerkelijk gepland is
Dus het doel werd:
Teams bestaan, maar nog niet actief zijn
De truc: een Team niet direct maken
De oplossing zat niet in een instelling, maar in de volgorde van bouwen.
In plaats van direct een Team te maken:
- Maak een
educationClass - Laat Microsoft de onderliggende group creëren
- Voeg een owner toe
- Promoveer daarna pas naar een Team
Door deze volgorde ontstaat een Team dat niet meteen actief gebruikt wordt.
Het doel was dus niet:
Teams maken
Maar:
Controleren wanneer een Team “tot leven komt”
Van stappen naar state
De eerste aanpak was lineair:
maak → configureer → klaar
Maar dat werkt niet met een asynchrone API.
Dus ik ben het anders gaan bekijken:
Wat zou de situatie moeten zijn?
En:
Wat is de situatie nu?
Het verschil daartussen bepaalt de actie.
HelloID als intent engine
In mijn model doet HelloID slechts één ding:
Bepalen wat er moet gebeuren
Niet uitvoeren. Tenminste… niet altijd.
Het resultaat daarvan is een lijst acties:
CreateClass
AddOwnerToGroup
CreateTeamFromClass
Undelete
Azure Automation als uitvoerder
Kleine batches worden direct uitgevoerd in HelloID. Een HelloID script heeft een runtime van 30 seconden. Dat is prima — tot je bij de start van het schooljaar ineens 2500 teams moet maken.
Grotere batches worden offloaded naar Azure Automation.
Belangrijk detail:
Azure weet niet WAT er moet gebeuren
Alleen:
VOERT uit wat HelloID heeft bepaald
Deze scheiding maakt het systeem simpel en robuust.
Eerlijk is eerlijk: het idee om naar Azure te offloaden komt van Randolf, van Speyk. Ik sta hier letterlijk op de schouders van iemand anders.
De realiteit van Microsoft Graph
Microsoft Graph werkt niet synchroon.
Bijvoorbeeld:
Team creation → 202 Accepted
Dat betekent:
- de resource bestaat nog niet volledig
- volgende acties kunnen falen
Een lineair script kan daar niet mee omgaan.
Inactive Teams als uitgangspunt
Een belangrijk ontwerpdoel was:
Teams mogen niet direct actief zijn
Dit is geen bijeffect van de techniek. Dit is het doel van het ontwerp.
Deze aanpak zorgt daarvoor, maar introduceert een constraint:
- Teams endpoint → kan geen members toevoegen
- Groups endpoint → kan dat wel
Dus:
Group = primaire resource
Team = laag erboven
Membership probleem
Dan volgt er nog een interessante situatie:
teams worden gemaakt vanuit docenten
een leerling kan in een team horen,
maar dat team bestaat alleen als er een docent is
De klassieke oplossing:
check eerst of team bestaat
Maar dat betekent:
- extra calls
- complexere logica
- race conditions
De keuze: niet controleren
In plaats daarvan doe ik dit:
probeer toe te voegen
faalt het → volgende run probeert opnieuw
Dat voelt eerst fout.
Maar is het niet.
De fout is geen fout
De fout betekent:
desired state ≠ current state
En dus:
nog niet uitvoerbaar
Bij een volgende run:
state veranderd → actie lukt
Het systeem convergeert vanzelf.
En als een lesgroep nooit een docent krijgt, dan ontstaat er dus ook nooit een Team.
Waarom dit beter werkt
Door niet te controleren:
- minder code
- minder afhankelijkheden
- minder timing issues
En belangrijker:
je blijft dicht bij het state model
Uiteindelijk inzicht
Veel systemen proberen fouten te voorkomen.
Maar in een asynchroon systeem kan dat niet.
Je kunt alleen zorgen dat fouten tijdelijk zijn.
Tot slot
Dit systeem maakt geen Teams.
Het bepaalt wanneer ze mogen bestaan.
En accepteert dat ze niet altijd meteen bestaan.
Soms zelfs dat ze nooit bestaan.
Dat voelt in het begin ongemakkelijk.
Maar levert uiteindelijk een systeem op dat zichzelf herstelt.
En dat is uiteindelijk robuuster dan elk perfect lineair script.
Als dit je nieuwsgierigheid triggert, vertel ik er graag meer over. De volledige documentatie en scripts deel ik liever niet publiek, maar in een 1‑op‑1 gesprek laat ik het graag zien. .