AutoMate Technisch Help

IAM HR Sync Jobs

Overzicht

De IAM HR Sync functionaliteit gebruikt een batch-based pipeline van background jobs die sequentieel worden uitgevoerd. De jobs worden automatisch gescheduled via een dispatcher, of kunnen handmatig getriggerd worden vanuit de frontend.

Job Pipeline

Dispatcher Job (Scheduler)

Job: IamEmployeeScheduleDispatcherJob Display Name: "IAM Employee Dispatch HR Sync jobs" Schedule: Elke 15 minuten (via Hangfire recurring job) Duur: < 1 seconde

Verantwoordelijkheden:

  • Scant alle tenants met actieve HR Sync configuratie

  • Checkt of een sync run gepland staat volgens de CRON schedule

  • Voorkomt concurrent execution - max 1 sync per tenant tegelijk

  • Enqueued Job 1 (PreConfigurationCheckJob) in een Hangfire batch

Concurrency Control: De dispatcher voorkomt race conditions door:

  • Primary guard: Check Hangfire storage voor actieve jobs

  • Secondary guard: Check IAM tables voor running batches

  • Tertiary guard: Check last known job state

Logging:

[IAM Dispatcher] Tick at 2025-12-30T15:00:00Z, scanning window 14:45 - 15:00 [IAM Dispatcher] Enqueued IAM Employee sync batch {BatchId} for tenant {TenantId}

Pipeline Jobs (Sequentieel Uitgevoerd)

Wanneer de dispatcher een sync triggert, wordt een batch aangemaakt met de volgende jobs. Deze draaien altijd sequentieel via ContinueJobWith - er zijn geen race conditions mogelijk.

Job 1: Pre-Configuration Check

Job: IamEmployeePreConfigurationCheckJob Display Name: "IAM Employee Pre configuration check" Duur: ~5-10 seconden

Verantwoordelijkheden:

  • πŸ” Resolve pipeline op basis van DestinationName uit tenant sync settings

  • βœ… Voert alle pre-configuratie checks uit die bij de pipeline horen

  • βœ… Schedule pipeline jobs in de batch (als checks slagen)

Pipeline-specifieke checks:

Pipeline

Checks

Entra AD

ProvisioningSchema, Credentials, JobActive, SchemaHashPresent, SchemaHashMatch, EmailConfiguration

Entra

EmailConfiguration

Bij failure:

  • Disable (prioriteit laag): Scheduled IamEmployeeDisableSyncJob en stopt de pipeline

  • Fail (prioriteit hoog): Markeert batch als failed en gooit exception

  • Bij meerdere failures: de check met de laagste FailurePriority bepaalt de actie

Logging:

[IAM PreCheck] Resolved pipeline: HR --> IAM Employee Processing Batch for destination: Entra AD [IAM PreCheck] Running check: ProvisioningSchema [IAM PreCheck] Check ProvisioningSchema: PASSED [IAM PreCheck] All validations passed - starting pipeline: HR --> IAM Employee Processing Batch

Output:

  • Persists step result in IAM_Employee_Sync_Batch_Steps (backward-compatible JSON)

  • Bij success: scheduledt pipeline-specifieke jobs

Job 2: Get HR Data

Job: IamEmployeeGetHrDataJob Display Name: "IAM Employee GetHrData" Duur: ~30-60 seconden (afhankelijk van HR-systeem response tijd)

Verantwoordelijkheden:

  • Ophalen van alle employees uit de source connector (bijv. SAP SuccessFactors)

  • Roept ISourceConnector.GetEmployeesAsync() aan

  • Geen filtering - haalt complete dataset op

Logging:

[IAM GetHrData] Fetched {Count} employees from source

Output:

  • Serialized employee list naar JSON

  • Opgeslagen in IAM_Employee_Sync_Batch_Steps (step 2)

Job 3: Translate HR Data

Job: IamEmployeeTranslateHrDataJob Display Name: "IAM Employee TranslateHRData" Duur: ~10-30 seconden

Verantwoordelijkheden:

  • Haalt employees op uit Job 2 output

  • Past destination translation schema toe (welke velden actief zijn)

  • Voert domain validation uit (UPN moet in Entra domains)

  • Detecteert duplicaten in source data

  • Filtert employees met ongeldige domains of duplicaten uit

  • Merge unmatched source employees met schema compliance

Validaties:

  • βœ… UPN domain in Entra domain list?

  • βœ… Geen duplicate EmployeeId/Email/Username?

  • βœ… Velden enabled in destination schema?

Logging:

[IAM TranslateHRData] Source after domain validation: {Count} (removed {RemovedCount} with invalid domains) [IAM TranslateHRData] Source after duplicate check: Valid = {ValidCount}, Duplicates = {DuplicateCount}

Output:

  • Filtered en validated employee list

  • Opgeslagen in IAM_Employee_Sync_Batch_Steps (step 3)

Job 4: Send to Entra Provisioning

Job: IamEmployeeSendToEntraProvisioningJob Display Name: "IAM Employee SendToEntraProvisioning" Duur: ~1-5 minuten (afhankelijk van aantal employees)

Verantwoordelijkheden:

  • Haalt validated employees uit Job 3 output

  • Bouwt SCIM 2.0 BulkRequest payloads (max 50 per batch)

  • Submits bulkUpload requests naar Microsoft Graph API

  • Slaat batch IDs op voor latere log retrieval

Batching:

  • Max 50 employees per SCIM bulk request

  • Bij 245 employees → 5 batches van 50 + 1 batch van 45

Logging:

[IAM SendToEntraProvisioning] Preparing {UserCount} users into {BatchCount} batches of up to 50 [IAM SendToEntraProvisioning] Submitted SCIM bulkUpload batch {BatchId} with {Count} users

Output:

  • List van submission batch IDs

  • Opgeslagen in IAM_Employee_Sync_Batch_Steps (step 4)

Job 5: Read Logs

Job: IamEmployeeReadLogsJob Display Name: "IAM Employee ReadLogs" Duur: ~2-10 minuten (afhankelijk van provisioning completion)

Verantwoordelijkheden:

  • Haalt batch IDs uit Job 4 output

  • Pollt Microsoft Graph API voor provisioning logs

  • Wacht tot alle batches compleet zijn (max timeout)

  • Parseert logs voor succesvolle creations en errors

  • Identificeert nieuwe accounts die een initial password nodig hebben

Polling:

  • Interval: elke 10 seconden

  • Max duration: 30 minuten

  • Stopt wanneer alle batches status "Completed" hebben

Logging:

[IAM ReadLogs] Polling for batch {BatchId} completion... [IAM ReadLogs] Batch {BatchId} status: {Status} [IAM ReadLogs] Found {Count} newly created users needing initial password

Output:

  • List van nieuwe user UPNs

  • Opgeslagen in IAM_Employee_Sync_Batch_Steps (step 5)

Job 6: Set Initial Password

Job: IamEmployeeSetInitialPasswordJob Display Name: "IAM Employee SetInitialPassword" Duur: ~30-120 seconden

Verantwoordelijkheden:

  • Haalt nieuwe user UPNs uit Job 5 output

  • Genereert random initial passwords

  • Zet passwords via Microsoft Graph API

  • Verstuurt password emails naar geconfigureerd email adres

  • Markeert users als "ForceChangePasswordNextSignIn"

Email:

  • Naar: IAM_Employee_Sync_Settings.InitialPasswordEmailFixedTo

  • Bevat: UPN en initial password per nieuwe user

Logging:

[IAM SetInitialPassword] Setting initial password for {Count} new users [IAM SetInitialPassword] Password set for {UPN} [IAM SetInitialPassword] Sent password email to {EmailAddress}

Output:

  • Success/failure status per user

  • Opgeslagen in IAM_Employee_Sync_Batch_Steps (step 6)

Job 7: Update Fields

Job: IamEmployeeUpdateFieldsJob Display Name: "IAM Employee UpdateFields" Duur: ~10-30 seconden

Verantwoordelijkheden:

  • Update employee fields in local database (nog niet geïmplementeerd in huidige versie)

  • Placeholder voor toekomstige field updates

Logging:

[IAM UpdateFields] Update fields job running for tenant {TenantId}

Job 8: Trigger Workflows

Job: IamEmployeeTriggerWorkflowsJob Display Name: "IAM Employee TriggerWorkflows" Duur: ~5-15 seconden

Verantwoordelijkheden:

  • Triggert workflow dispatcher jobs voor nieuwe/gewijzigde employees

  • Enqueued WorkflowEmployeeCreatedDispatcherJob voor nieuwe users

  • Enqueued WorkflowEmployeeUpdatedDispatcherJob voor updates

Logging:

[IAM TriggerWorkflows] Triggering workflows for tenant {TenantId} [IAM TriggerWorkflows] Enqueued created dispatcher for {Count} new employees [IAM TriggerWorkflows] Enqueued updated dispatcher for {Count} modified employees

Output:

  • Workflow job IDs

  • Opgeslagen in IAM_Employee_Sync_Batch_Steps (step 8)

Job Dependencies (Sequentieel)

De pipeline wordt dynamisch bepaald op basis van de DestinationName uit de tenant settings.

Entra AD Pipeline (Hybrid Identity)

Enqueues

Resolve: Entra AD

If OK

If Failed

Dispatcher: Schedule Check

Job 1: PreConfigurationCheck

6 Checks uitvoeren

Job 2: GetHrData

DisableSyncJob

Job 3: TranslateHrData

Job 4: SendToEntraProvisioning

Job 5: ReadLogs

Job 6: SetInitialPassword

Job 7: UpdateFields

Job 8: TriggerWorkflows

Complete

Entra Pipeline (Cloud-only)

Enqueues

Resolve: Entra

If OK

If Failed

Dispatcher: Schedule Check

Job 1: PreConfigurationCheck

1 Check uitvoeren

Job 2: GetHrData

DisableSyncJob

Job 3: TranslateHrData

Job 4: DetermineActions

Job 5: BatchGraphRequests

Job 6: TriggerWorkflows

Complete

Belangrijke eigenschappen:

  • βœ… Jobs draaien altijd sequentieel via Hangfire ContinueJobWith

  • βœ… Geen race conditions - elke job wacht op de vorige

  • βœ… Max 1 sync per tenant tegelijk - dispatcher voorkomt concurrency

  • βœ… Atomic batches - hele pipeline slaagt of faalt als geheel

  • βœ… Audit trail - elke step result wordt opgeslagen

  • βœ… Pipeline per bestemming - checks en jobs worden dynamisch bepaald

Triggering

Automatisch (Scheduled)

Configuratie per tenant:

  • CRON schedule in IAM_Employee_Sync_Settings.ScheduleCron

  • Voorbeeld: 0 2 * * * (dagelijks om 02:00 UTC)

  • Voorbeeld: 7,37 * * * * (elk uur op minuut 7 en 37)

Dispatcher:

  • Draait elke 15 minuten

  • Scant 15-minuten window voor scheduled runs

  • Enqueued alleen als CRON match binnen window

Handmatig (Frontend)

Via Management Portal:

  1. Ga naar IAM HR SyncSync

  2. Klik op "Start Sync Now" (triggert Job 1 via API)

  3. Monitor voortgang in Aspire Dashboard of Jobs dashboard

API Endpoint (optioneel):

POST /api/iam/employee-sync/trigger { "tenantId": "guid", "dryRun": false }

Externe Opslag Transfer Jobs

Naast de sync pipeline zijn er twee aparte jobs verantwoordelijk voor het nachtelijk exporteren van gefinaliseerde audit log batches naar externe opslag. Ze staan volledig los van de sync pipeline: een mislukte transfer blokkeert nooit een sync run.

IamEmployeeAuditLogStorageDispatcherJob

Beheert de lifecycle van nachtelijke recurring transfer jobs per tenant. Registreert een Hangfire recurring job (CRON 0 2 * * *, tenant timezone) voor elke tenant met ExternalStorageEnabled = true, en verwijdert verouderde recurring jobs voor tenants die externe opslag hebben uitgeschakeld.

IamEmployeeAuditLogStorageTransferJob

Draait nachtelijk om 02:00 per tenant. Haalt gefinaliseerde audit log batches op sinds het laatste watermark (ExternalStorageLastTransferredAt), streamt de records naar JSON en uploadt ze naar de geconfigureerde opslaglocatie als yyyy-MM-dd/HH-mm-ss_iam-sync-audit-log.json. Bij een mislukte upload herprobeert Hangfire tot 3 keer; pas na de definitief mislukte poging wordt een e-mailnotificatie verstuurd.

Retry attributes: [AutomaticRetry(Attempts = 3)], [DisableConcurrentExecution(timeoutInSeconds: 900)]

Zie IAM HR Sync — Externe Opslag Transfer voor de volledige technische beschrijving, inclusief flow, retry-gedrag, silent-skip guards en watermark-integriteit.

Monitoring

Job Dashboard URLs

Productie:

https://p-automate-portal-webapi-webapp-weu.azurewebsites.net/jobs https://p-automate-portal-webapi-webapp-weu.azurewebsites.net/jobs/retries

Development:

https://d-automate-portal-webapi-webapp-weu.azurewebsites.net/jobs https://d-automate-portal-webapi-webapp-weu.azurewebsites.net/jobs/retries

Local/Test:

http://localhost:8080/jobs

Via Hangfire Dashboard

  1. Ga naar de job dashboard URL voor jouw omgeving

  2. Zoek naar "IAM Employee" jobs

  3. Check status: Enqueued, Processing, Succeeded, Failed

  4. Bij failures: check "Failed" tab voor error details

Via Aspire Dashboard (Development)

  1. Open Aspire Dashboard (http://localhost:15888)

  2. Ga naar Traces tab

  3. Filter op "IAM Employee" of tenant ID

  4. Bekijk distributed trace voor complete pipeline

Via Audit Logs

Alle jobs loggen naar IAM_Employee_Sync_Batches:

SELECT * FROM IAM_Employee_Sync_Batches WHERE TenantId = @TenantId ORDER BY CreatedAt DESC

Per-step results:

SELECT * FROM IAM_Employee_Sync_Batch_Steps WHERE BatchId = @BatchId ORDER BY StepOrder

Troubleshooting

Job blijft hangen in "Processing"

Probleem: Job status blijft "Processing" en completeert niet.

Oplossing:

  1. Check Hangfire dashboard voor error details

  2. Check Aspire/Seq logs voor exceptions

  3. Bij timeout (>30 min): requeue handmatig via dashboard

  4. Check of source system bereikbaar is (voor Job 2)

Sync wordt automatisch disabled

Probleem: Job 1 scheduled een DisableSyncJob.

Oorzaak:

  • Schema hash mismatch

  • Provisioning job niet actief

  • Email configuratie ontbreekt

Oplossing:

  1. Check audit logs voor exacte reden

  2. Los probleem op (zie edge cases documentatie)

  3. Re-enable sync via Management Portal

Jobs draaien niet volgens schedule

Probleem: Dispatcher enqueued geen nieuwe sync.

Oorzaak:

  • CRON syntax incorrect

  • Sync not active in settings

  • Previous batch still running

Oplossing:

-- Check configuratie SELECT TenantId, ScheduleCron, SyncActive, LastJobId FROM IAM_Employee_Sync_Settings -- Check running batches SELECT * FROM IAM_Employee_Sync_Batches WHERE Status = 'Running'

Concurrent execution detected

Probleem: Dispatcher skipped enqueue omdat er al een batch draait.

Oorzaak:

  • Previous batch niet afgesloten

  • Hangfire job stuck

Oplossing:

  1. Check Hangfire voor stuck jobs

  2. Delete/requeue stuck job via dashboard

  3. Retry dispatcher na cleanup

Last modified: 04 June 2026