389 lines
11 KiB
Markdown
389 lines
11 KiB
Markdown
# Runtime Event Processing
|
|
|
|
Runtime Processing is now source-neutral. The API receives a runtime scope, selects a processing profile, partitions the normalized EventHub-style events, and delegates execution to the selected profile.
|
|
|
|
The tachograph Esper processing is no longer the root concept. It is one profile:
|
|
|
|
```text
|
|
tachograph-driver-esper-v1
|
|
```
|
|
|
|
## Profile discovery endpoint
|
|
|
|
```http
|
|
GET /api/eventhub/runtime-processing/event-processing/profiles
|
|
```
|
|
|
|
Example response:
|
|
|
|
```json
|
|
[
|
|
{
|
|
"profileKey": "tachograph-driver-esper-v1",
|
|
"displayName": "Tachograph Driver Esper Processing",
|
|
"description": "Runs the shared tachograph driver Esper processing pipeline over Runtime Processing event scopes.",
|
|
"defaultPartitioningStrategy": "DRIVER",
|
|
"supportedPartitioningStrategies": ["DRIVER"],
|
|
"requiredParameters": [],
|
|
"optionalParameters": [
|
|
"significantDrivingMinutes",
|
|
"minimumRestPeriodMinutes",
|
|
"attachVehicleOnlyEvents",
|
|
"vehicleEvidencePaddingMinutes",
|
|
"includePartitionDebug"
|
|
]
|
|
}
|
|
]
|
|
```
|
|
|
|
Clients should prefer this endpoint instead of hardcoding profile metadata.
|
|
|
|
## Generic execution endpoint
|
|
|
|
```http
|
|
POST /api/eventhub/runtime-processing/event-processing
|
|
```
|
|
|
|
## Request shape
|
|
|
|
```json
|
|
{
|
|
"profileKey": "tachograph-driver-esper-v1",
|
|
"scope": {
|
|
"sessionIds": [
|
|
"11111111-1111-1111-1111-111111111111",
|
|
"22222222-2222-2222-2222-222222222222"
|
|
],
|
|
"sourceFamilies": ["TACHOGRAPH_FILE_SESSION"],
|
|
"occurredFrom": "2026-05-01T00:00:00Z",
|
|
"occurredTo": "2026-05-31T23:59:59Z",
|
|
"expandVehicleEvents": true,
|
|
"vehicleExpansionPaddingMinutes": 15
|
|
},
|
|
"partitioning": {
|
|
"strategy": "DRIVER",
|
|
"includeAllPartitions": true,
|
|
"attachVehicleEvidence": true,
|
|
"vehicleEvidencePaddingMinutes": 15,
|
|
"includeDebug": true
|
|
},
|
|
"parameters": {
|
|
"significantDrivingMinutes": 3,
|
|
"minimumRestPeriodMinutes": 720,
|
|
"attachVehicleOnlyEvents": true,
|
|
"vehicleEvidencePaddingMinutes": 15,
|
|
"includePartitionDebug": true
|
|
}
|
|
}
|
|
```
|
|
|
|
## Response shape
|
|
|
|
```json
|
|
{
|
|
"profileKey": "tachograph-driver-esper-v1",
|
|
"partitioningStrategy": "DRIVER",
|
|
"inputEventCount": 1234,
|
|
"selectedPartitionCount": 2,
|
|
"discoveredVehicleCount": 3,
|
|
"partitionResults": {
|
|
"12:12345678901234": {
|
|
"partitionType": "DRIVER",
|
|
"partitionKey": "12:12345678901234",
|
|
"resultType": "UnifiedRuntimeDerivedProjectionResultDto",
|
|
"result": {
|
|
"projection": {
|
|
"activityIntervals": [],
|
|
"drivingIntervals": [],
|
|
"drivingInterruptionIntervals": [],
|
|
"dailyWeeklyRestCandidateIntervals": [],
|
|
"dailyWeeklyRestCandidateCoverageIntervals": [],
|
|
"unclassifiedDailyWeeklyRestCandidateCoverageIntervals": [],
|
|
"potentialHomeOvernightStayIntervals": [],
|
|
"potentialInVehicleOvernightStayIntervals": [],
|
|
"potentialInVehicleTripIntervals": [],
|
|
"vehicleUsageIntervals": [],
|
|
"vuCardAbsentIntervals": [],
|
|
"supportGeoEvents": []
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"notes": [],
|
|
"warnings": []
|
|
}
|
|
```
|
|
|
|
## Concepts
|
|
|
|
### Scope
|
|
|
|
`scope` is the existing runtime selection model. It can select events from:
|
|
|
|
```text
|
|
TACHOGRAPH_FILE_SESSION
|
|
TACHOGRAPH_DB
|
|
YELLOWFOX_DB
|
|
```
|
|
|
|
and can use:
|
|
|
|
```text
|
|
SOURCE_DB
|
|
EVENTHUB_DB
|
|
```
|
|
|
|
where supported.
|
|
|
|
For uploaded tachograph files, the scope can use:
|
|
|
|
```text
|
|
sessionId
|
|
sessionIds
|
|
compositeSessionId
|
|
```
|
|
|
|
### Profile
|
|
|
|
A profile owns domain-specific processing semantics. It defines:
|
|
|
|
```text
|
|
profile key
|
|
expected partitioning strategy
|
|
profile-specific parameters
|
|
result type
|
|
```
|
|
|
|
Current profile:
|
|
|
|
```text
|
|
tachograph-driver-esper-v1
|
|
```
|
|
|
|
Future profiles can include:
|
|
|
|
```text
|
|
vehicle-stop-detection-v1
|
|
vehicle-trip-detection-v1
|
|
telematics-poi-clustering-v1
|
|
driver-settlement-v1
|
|
mixed-driver-vehicle-correlation-v1
|
|
```
|
|
|
|
### Partitioning
|
|
|
|
The common API supports generic partitioning options:
|
|
|
|
```text
|
|
NONE
|
|
DRIVER
|
|
VEHICLE
|
|
DRIVER_VEHICLE
|
|
SOURCE_FAMILY
|
|
CUSTOM_PROFILE
|
|
```
|
|
|
|
The first tachograph profile currently supports `DRIVER` partitioning. The service partitions mixed event scopes in Java before invoking Esper so that existing single-driver EPL windows cannot mix driver states.
|
|
|
|
## Partition debug / audit output
|
|
|
|
For mixed-source scopes, request debug output when validating why events were or were not attached to a driver partition:
|
|
|
|
```json
|
|
{
|
|
"partitioning": {
|
|
"strategy": "DRIVER",
|
|
"includeAllPartitions": true,
|
|
"attachVehicleEvidence": true,
|
|
"vehicleEvidencePaddingMinutes": 15,
|
|
"includeDebug": true
|
|
},
|
|
"parameters": {
|
|
"includePartitionDebug": true
|
|
}
|
|
}
|
|
```
|
|
|
|
When enabled, each generic `partitionResults[*].metadata.partitionDebug` contains:
|
|
|
|
```text
|
|
directDriverEventCount
|
|
vehicleUsageIntervalCount
|
|
candidateVehicleEvidenceEventCount
|
|
attachedVehicleEvidenceEventCount
|
|
ignoredVehicleEvidenceEventCount
|
|
mergedEventCount
|
|
vehicleUsageIntervals
|
|
vehicleEvidenceDecisions
|
|
notes
|
|
warnings
|
|
```
|
|
|
|
`vehicleEvidenceDecisions` explains every relevant decision, for example:
|
|
|
|
```text
|
|
DIRECT_DRIVER_EVENT
|
|
ATTACHED_VEHICLE_EVIDENCE
|
|
IGNORED_NO_OVERLAPPING_VEHICLE_USAGE
|
|
IGNORED_ATTACHMENT_DISABLED
|
|
```
|
|
|
|
The compatibility response type also has `partitionDebugByDriver`; use the generic endpoint when you need to enable debug output explicitly. Keep debug disabled for high-volume production requests unless you need attribution diagnostics, because the decision list can be large.
|
|
|
|
## Compatibility endpoint
|
|
|
|
The old tachograph endpoint remains available:
|
|
|
|
```http
|
|
POST /api/eventhub/runtime-processing/tachograph/esper-processing
|
|
```
|
|
|
|
It now acts as a compatibility adapter for:
|
|
|
|
```http
|
|
POST /api/eventhub/runtime-processing/event-processing
|
|
```
|
|
|
|
with:
|
|
|
|
```text
|
|
profileKey = tachograph-driver-esper-v1
|
|
partitioning.strategy = DRIVER
|
|
```
|
|
|
|
## Tachograph profile processing flow
|
|
|
|
```text
|
|
runtime event scope
|
|
-> broad event assembly
|
|
-> driver partition discovery
|
|
-> for each driver:
|
|
direct driver events
|
|
reconstruct driver vehicle-usage intervals
|
|
attach only vehicle-scoped events whose vehicle matches and whose timestamp falls inside a usage interval plus configured padding
|
|
shared event-input Esper projection pipeline
|
|
-> generic partitionResults map
|
|
```
|
|
|
|
The tachograph profile reuses the same `TachographEsperProcessingCore` used by the file-session endpoint. This prevents the file-session API and runtime-processing API from drifting into separate rule chains.
|
|
## Vehicle-only evidence attachment
|
|
|
|
For driver-partitioned profiles, vehicle-only events are no longer attached only by vehicle identity. They are attached to a driver partition only when there is temporal evidence:
|
|
|
|
```text
|
|
vehicle-only event.vehicleKey/registrationKey matches a reconstructed driver vehicle-usage interval
|
|
and event.occurredAt is inside [usage.from - padding, usage.to + padding]
|
|
```
|
|
|
|
This prevents unrelated vehicle events from being copied into a driver result simply because the driver used the same vehicle on another day. The tachograph profile currently uses:
|
|
|
|
```json
|
|
{
|
|
"partitioning": {
|
|
"attachVehicleEvidence": true,
|
|
"vehicleEvidencePaddingMinutes": 15,
|
|
"includeDebug": true
|
|
},
|
|
"parameters": {
|
|
"attachVehicleOnlyEvents": true,
|
|
"vehicleEvidencePaddingMinutes": 15,
|
|
"includePartitionDebug": true
|
|
}
|
|
}
|
|
```
|
|
|
|
`parameters` take precedence in the tachograph profile. The compatibility endpoint maps these values to `expandVehicleEvents` and `vehicleExpansionPaddingMinutes`.
|
|
|
|
|
|
## Tachograph parity validation
|
|
|
|
A validation endpoint is available to compare the legacy tachograph file-session Esper endpoint with the generic runtime event-processing profile:
|
|
|
|
```http
|
|
POST /api/eventhub/runtime-processing/event-processing/validation/tachograph-parity
|
|
```
|
|
|
|
This endpoint runs both paths for the selected session(s) and driver(s):
|
|
|
|
```text
|
|
legacy file-session path
|
|
/api/eventhub/tachograph-file-sessions/{sessionId}/drivers/{driverKey}/processing/esper-events
|
|
|
|
runtime event-processing path
|
|
/api/eventhub/runtime-processing/event-processing
|
|
profileKey = tachograph-driver-esper-v1
|
|
```
|
|
|
|
Example request:
|
|
|
|
```json
|
|
{
|
|
"sessionId": "{{sessionId}}",
|
|
"driverKey": "{{driverKey}}",
|
|
"occurredFrom": "2026-05-01T00:00:00Z",
|
|
"occurredTo": "2026-05-31T23:59:59Z",
|
|
"expandVehicleEvents": true,
|
|
"vehicleExpansionPaddingMinutes": 15,
|
|
"significantDrivingMinutes": 3,
|
|
"minimumRestPeriodMinutes": 720,
|
|
"includeDebug": true
|
|
}
|
|
```
|
|
|
|
For multiple uploaded tachograph sessions, use `sessionIds` or `compositeSessionId`. The validation service resolves the selected drivers, executes the generic runtime profile, then compares count-level parity per driver.
|
|
|
|
Compared categories include:
|
|
|
|
```text
|
|
activityIntervals
|
|
drivingIntervals
|
|
drivingInterruptionIntervals
|
|
drivingInterruptionVehicleChangeIntervals
|
|
dailyWeeklyRestCandidateIntervals
|
|
dailyWeeklyRestCandidateCoverageIntervals
|
|
unclassifiedDailyWeeklyRestCandidateCoverageIntervals
|
|
potentialHomeOvernightStayIntervals
|
|
potentialInVehicleOvernightStayIntervals
|
|
potentialInVehicleTripIntervals
|
|
vehicleUsageIntervals
|
|
vuCardAbsentIntervals
|
|
supportGeoEvents
|
|
```
|
|
|
|
For a single session, this is a direct parity check against the original file-session endpoint. For multiple sessions, the reference side is the sum of the individual file-session endpoint results per driver; runtime processing may intentionally deduplicate or merge across session boundaries, so differences should be reviewed with the debug/audit output.
|
|
|
|
## Runtime support evidence normalization
|
|
|
|
The tachograph profile now normalizes mixed-source support events before invoking the shared Esper core:
|
|
|
|
```text
|
|
runtime partition events
|
|
-> RuntimeSupportEvidenceNormalizer
|
|
-> tachograph-consumable support evidence view
|
|
-> event-input Esper preprocessor / driving-derived bundle
|
|
```
|
|
|
|
The normalizer does not change driver activity events or driver-card usage events. It only adapts support/vehicle events that carry geo or odometer evidence. Provider-specific semantics are preserved in the payload under `raw.originalEventDomain`, `raw.originalEventType`, `raw.originalLifecycle`, `raw.supportEventDomain`, and `raw.supportEventType`.
|
|
|
|
Examples:
|
|
|
|
```text
|
|
IGNITION / IGNITION_ON with position
|
|
-> POSITION / POSITION_RECORDED / SNAPSHOT
|
|
-> raw.supportEventType = IGNITION_ON
|
|
|
|
TELEMATICS_DATA with position
|
|
-> POSITION / POSITION_RECORDED / SNAPSHOT
|
|
-> raw.supportEventType = TELEMATICS_DATA
|
|
|
|
BORDER_CROSSING with position
|
|
-> BORDER_CROSSING, preserving the original border event type/lifecycle
|
|
|
|
LOAD_UNLOAD with position
|
|
-> LOAD_UNLOAD, preserving the original load/unload event type/lifecycle
|
|
```
|
|
|
|
This keeps the EPL rules provider-neutral. YellowFox, tachograph VU, or future telematics events are converted to the common support-evidence shape before the tachograph profile consumes them.
|
|
|
|
Runtime result notes include how many events were inspected and how many support events were adapted. Use partition debug together with normalization notes when validating mixed-source attribution.
|