GetSportingEventsQuery — Filter Mode Reference¶
GetSportingEventsQuery supports three mutually exclusive filter modes resolved by a fixed priority ladder. The handler picks exactly one mode per request; parameters that don't apply to the selected mode are ignored.
Priority Order¶
| Priority | Mode | Fires when |
|---|---|---|
| 1 (highest) | CurrentGroup |
CurrentGroupOnly = true AND Sport is set |
| 2 | DateRange |
StartDate or EndDate is set |
| 3 (lowest) | NamedGroup |
Group AND Sport are set, no dates provided |
| default | DateRange |
None of the above — today +/- 2 days |
Groupis only used as a filter inNamedGroupmode. IfStartDateorEndDateis also provided,DateRangetakes priority andGroupis ignored entirely.
Decision Flowchart¶
CurrentGroupOnly = true AND Sport set?
YES → CurrentGroup (resolve CurrentGroupName from SeasonContract)
NO ↓
StartDate OR EndDate set?
YES → DateRange (Group is ignored even if set)
NO ↓
Group set AND Sport set?
YES → NamedGroup (SeasonId-scoped, Group filter applied)
NO ↓
Default → DateRange with today ± 2 days
Mode Details¶
1. CurrentGroup (highest priority)¶
Resolves the active group name from SeasonContract and returns all events in that group for the current season.
Requires: CurrentGroupOnly = true, Sport set
Ignores: StartDate, EndDate, Group
How it works:
1. Queries all SeasonContract records filtered by sport, CurrentSeason = true, and non-empty CurrentGroupName, ordered by SeasonYear descending. Multiple competitions within the same sport (e.g., NRL and Super League for Rugby League) can each have their own current season.
2. If no matching seasons are found, returns an empty result.
3. Scopes the sporting events query to all matching SeasonIds using an IN clause, then applies per-season group filtering in memory — each season's events are filtered to only include its own CurrentGroupName (e.g., NRL "Round 15" and Super League "Round 18" can coexist in the same result).
Returns empty when: No SeasonContract exists with CurrentSeason = true and a non-empty CurrentGroupName for the given sport.
Examples:
// Fires CurrentGroup — resolves the active group name from SeasonContract
Sport: "NRL", CurrentGroupOnly: true
// Also fires CurrentGroup — StartDate/EndDate are present but ignored
Sport: "NRL", CurrentGroupOnly: true, StartDate: "2026-06-01", EndDate: "2026-06-30"
// Falls through to default DateRange — CurrentGroupOnly requires Sport to be set
CurrentGroupOnly: true
2. DateRange¶
Returns events within a date window. This is both the explicit date filter and the default fallback.
Requires: StartDate or EndDate set (or neither — falls back to today +/- 2 days)
Ignores: Group (even if set)
How it works:
1. Queries SportingEventContract where StartTimeUtc falls within [startDate, endDate].
2. Applies the sport filter if Sport is set.
3. If IsInitialLoad = true and no results are found in the window, jumps to the nearest future date with events and re-queries a 5-day span from that date.
Default dates (when neither StartDate nor EndDate provided):
filterStartDate = today - 2 days
filterEndDate = today + 2 days
Examples:
// Explicit DateRange
Sport: "NRL", StartDate: "2026-06-20", EndDate: "2026-06-27"
// Default DateRange — no params, returns today ± 2 days across all sports
(empty query)
// Default DateRange with sport filter
Sport: "NRL"
// DateRange wins over NamedGroup — StartDate takes priority even when Group is set
Sport: "NRL", Group: "Round 5", StartDate: "2026-06-20"
// DateRange with IsInitialLoad — jumps to the nearest future round when today ± 2 is empty
Sport: "NRL", IsInitialLoad: true
3. NamedGroup (lowest priority)¶
Returns events for a specific named group within the current season, scoped by SeasonId. Only fires when no date parameters are provided.
Requires: Group set, Sport set, StartDate not set, EndDate not set
Ignores: Nothing — if dates were set, DateRange would fire instead
How it works:
1. Queries all SeasonContract records filtered by sport and CurrentSeason = true, ordered by SeasonYear descending. Multiple competitions within the same sport can each have their own current season.
2. If no current seasons are found, returns an empty result.
3. Scopes the sporting events query to all matching SeasonIds using an IN clause and filters by Group == query.Group.
Returns empty when: No SeasonContract exists with CurrentSeason = true for the given sport.
Examples:
// Fires NamedGroup — no dates, group + sport set
Sport: "NRL", Group: "Round 5"
// Also fires NamedGroup
Sport: "AFL", Group: "Semi Final"
// Falls through to default DateRange — Group requires Sport
Group: "Round 5"
// Fires DateRange, NOT NamedGroup — StartDate takes priority
Sport: "NRL", Group: "Round 5", StartDate: "2026-06-20"
// Fires CurrentGroup, NOT NamedGroup — CurrentGroupOnly wins
Sport: "NRL", Group: "Round 5", CurrentGroupOnly: true
Cache Key Format¶
| Mode | Key format |
|---|---|
CurrentGroup |
sporting-events:{Sport}:current-group |
DateRange (explicit) |
sporting-events:{Sport\|all}:{startDate:yyyy-MM-dd}:{endDate:yyyy-MM-dd} |
DateRange (default) |
sporting-events:{Sport\|all}:{today-2:yyyy-MM-dd}:{today+2:yyyy-MM-dd} |
NamedGroup |
sporting-events:{Sport}:group:{Group} |
The cache key is resolved in GetSportingEventsQuery.CacheKey using the same priority logic as the handler, so cache lookups are always consistent with what the handler would execute.
Cache TTL¶
CurrentGroup and NamedGroup are always treated as small-range regardless of any date values, because they scope by SeasonId rather than a date window.
| Condition | TTL |
|---|---|
| Small-range (group mode or date span <= 10 days) with live match | 10 seconds |
| Small-range with match starting within 10 minutes | 10 seconds |
| Small-range, no live or imminent match | 30 seconds |
| Large-range (date span > 10 days) | 10 minutes |
ETag Format¶
| Mode | ETag input string |
|---|---|
CurrentGroup |
{Sport}-CurrentGroup-{group1\|group2\|...}-{count} (sorted, deduplicated) |
NamedGroup |
{Sport}-NamedGroup-{groupName}-{count} |
DateRange |
{Sport\|all}-{effectiveStartDate:yyyy-MM-dd}-{effectiveEndDate:yyyy-MM-dd}-{count} |
The ETag is the hex hash (ToString("x8")) of the input string. For DateRange with IsInitialLoad, effectiveStartDate/effectiveEndDate reflect the jumped-to window rather than the original query dates.
Cache Tags¶
The response is tagged for granular invalidation. Tags emitted per request:
| Tag | Always emitted | Conditionally emitted |
|---|---|---|
sportingevents |
Yes | |
{Sport} |
When Sport is set |
|
se:{EventId} |
One per sporting event in result | |
group:{GroupName} |
One per distinct group name in result |