Sign in to run and submit your work
Reading is open to everyone. Running code and saving drafts need an account so your work is yours and comes back on your next visit.
or
CODE WORKSPACE
The streaming aggregate counts events in five-minute windows. It currently buckets them by when the consumer read them, which means a mobile client that was offline for an hour has its events counted in the wrong window — and the daily totals still reconcile, so nobody has noticed.
Write assign_windows(events, window_seconds, allowed_lateness). Each event carries an event_time and a processing_time.
Function to write
assign_windows(events: list[dict], window_seconds: int, allowed_lateness: int) -> dictA dict with windows — each with start, end and sorted event ids — and late, the events that missed theirs.
How to approach it
Convert both timestamps to epoch seconds; the window start is then one modulo away.
Sample cases
+ 2 held back until you submit
a five-minute tumble
An event on the window boundary, one that is late but inside the grace period, one hours late, and one unparseable.
Input
Argument 1
| id | event_time | processing_time |
|---|---|---|
| e1 | 2026-03-02T09:00:10Z | 2026-03-02T09:00:12Z |
| e2 | 2026-03-02T09:04:59Z | 2026-03-02T09:05:01Z |
| e3 | 2026-03-02T09:05:00Z | 2026-03-02T09:05:02Z |
| e4 | 2026-03-02T09:01:00Z | 2026-03-02T09:07:30Z |
| e5 | 2026-03-02T09:02:00Z | 2026-03-02T11:00:00Z |
| e6 | not a timestamp | 2026-03-02T09:06:00Z |
Argument 2
300Argument 3
120Returns
{
'windows': [
{
'window_start': '2026-03-02T09:00:00Z',
'window_end': '2026-03-02T09:05:00Z',
'events': [
'e1',
'e2'
]
},
{
'window_start': '2026-03-02T09:05:00Z',
'window_end': '2026-03-02T09:10:00Z',
'events': [
'e3'
]
}
],
'late': [
{
'id': 'e4',
'reason': 'too_late',
'window_start': '2026-03-02T09:00:00Z'
},
{
'id': 'e5',
'reason': 'too_late',
'window_start': '2026-03-02T09:00:00Z'
},
{
'id': 'e6',
'reason': 'unusable_timestamp',
'window_start': None
}
]
}no events
An idle period produces no windows and no late events rather than an empty window.
Input
Argument 1
[] (empty list)
Argument 2
300Argument 3
120Returns
{
'windows': [],
'late': []
}no grace at all
With zero lateness allowed, anything arriving after its window closed is diverted.
Input
Argument 1
| id | event_time | processing_time |
|---|---|---|
| e1 | 2026-03-02T09:00:10Z | 2026-03-02T09:00:12Z |
| e2 | 2026-03-02T09:04:59Z | 2026-03-02T09:05:01Z |
| e3 | 2026-03-02T09:05:00Z | 2026-03-02T09:05:02Z |
| e4 | 2026-03-02T09:01:00Z | 2026-03-02T09:07:30Z |
| e5 | 2026-03-02T09:02:00Z | 2026-03-02T11:00:00Z |
| e6 | not a timestamp | 2026-03-02T09:06:00Z |
Argument 2
300Argument 3
0Returns
{
'windows': [
{
'window_start': '2026-03-02T09:00:00Z',
'window_end': '2026-03-02T09:05:00Z',
'events': [
'e1'
]
},
{
'window_start': '2026-03-02T09:05:00Z',
'window_end': '2026-03-02T09:10:00Z',
'events': [
'e3'
]
}
],
'late': [
{
'id': 'e2',
'reason': 'too_late',
'window_start': '2026-03-02T09:00:00Z'
},
{
'id': 'e4',
'reason': 'too_late',
'window_start': '2026-03-02T09:00:00Z'
},
{
'id': 'e5',
'reason': 'too_late',
'window_start': '2026-03-02T09:00:00Z'
},
{
'id': 'e6',
'reason': 'unusable_timestamp',
'window_start': None
}
]
}Constraints
window_seconds at or before its event time.allowed_lateness seconds after its window's end. Put it in late with the window it should have been in, rather than in that window.late with the reason unusable_timestamp and no window.Z, with an offset, or with no zone. Treat a zoneless timestamp as UTC and compare everything in UTC.Worked example
e2 happened at 09:04:59 and e3 at 09:05:00, one second apart. They land in different windows — the first in the one starting at 09:00, the second in the one starting at 09:05 — because the boundary belongs to the window that starts on it. Getting that backwards moves one event per boundary, forever, in a way that never shows up in a total.
e4 happened at 09:01 and arrived at 09:07:30. Its window closed at 09:05, so it is two and a half minutes late — inside a two-minute grace? No: 09:07:30 is 150 seconds after 09:05, and the allowance is 120, so it is diverted. e5 happened at 09:02 and arrived at 11:00, nearly two hours late. Counting either of them in the window they arrived in is how the mobile clients' traffic ended up attributed to the moment their signal came back.
What this tests
The distinction between event time and processing time, which is the central idea in stream processing, and floor division on an aligned grid. The boundary rule and the lateness rule are both places where a defensible-looking choice is wrong.
assign_windows(events: list[dict], window_seconds: int, allowed_lateness: int) -> dictSubmit for review to find out what your query gets right, what it gets wrong, and how it compares with the best working query for this exercise.
This scenario runs a full workspace — editor, canvas and results side by side. It needs a laptop or desktop to be usable. Open this page on a bigger screen to start building.