Skip to content

Add HasDataChangedAsync for lightweight change detection via HEAD request#47

Open
jfversluis wants to merge 1 commit intonikneem:mainfrom
jfversluis:feature/has-data-changed
Open

Add HasDataChangedAsync for lightweight change detection via HEAD request#47
jfversluis wants to merge 1 commit intonikneem:mainfrom
jfversluis:feature/has-data-changed

Conversation

@jfversluis
Copy link
Copy Markdown

@jfversluis jfversluis commented Mar 30, 2026

Summary

Adds a new HasDataChangedAsync method to ISessionizeApiClient that uses Sessionize's built-in ?hashonly=true query parameter to fetch a lightweight hash of the data for any view endpoint, avoiding a full data download.

Motivation

Mobile and bandwidth-constrained apps (e.g., conference companion apps built with .NET MAUI) need to periodically check for schedule updates. The current approach requires a full GET request (~300KB for the All view). Sessionize supports a ?hashonly=true query parameter that returns only a ~40-byte SHA-1 hash of the data, which changes whenever the underlying data changes.

This is especially valuable for:

  • Mobile apps checking for updates on resume/startup
  • Apps implementing cache-first patterns with background refresh
  • Reducing unnecessary API traffic for unchanged data

How it works

Appending ?hashonly=true to any Sessionize view endpoint returns just the hash:

GET https://sessionize.com/api/v2/{apiId}/view/All?hashonly=true
→ aa94b4bbb12bdbcbb9b5059e7dfa37818ebd5f8e  (40 bytes, ~50ms)

GET https://sessionize.com/api/v2/{apiId}/view/All
→ Full JSON payload (~300KB)

Each view (All, Sessions, Speakers, GridSmart, SpeakerWall) returns its own hash.

Changes

New DTO

  • DataChangedResponse(bool HasChanged, string Hash) — a record containing whether data changed and the current server hash

Interface addition

  • ISessionizeApiClient.HasDataChangedAsync(viewName, lastKnownHash?, sessionizeApiId?, cancellationToken?)
    • viewName: The Sessionize view to check (e.g., "All", "Sessions", "Speakers", "GridSmart", "SpeakerWall")
    • lastKnownHash: The hash from a previous call. If null, returns HasChanged=true with the current server hash
    • Same sessionizeApiId and cancellationToken pattern as existing methods

Implementation

  • Sends a GET request to {apiId}/view/{viewName}?hashonly=true
  • Reads the plain-text hash response
  • Compares against the provided lastKnownHash (case-insensitive)
  • Reuses the existing GetViewEndpoint() helper for consistent URL construction
  • Follows existing logging patterns with ILogger

Tests

  • 7 unit tests — mocked HttpClient verifying request URL construction, hash comparison scenarios (no previous hash, different hash, matching hash, case-insensitive comparison, empty response, explicit API ID)
  • 6 integration tests — live API calls verifying real hash behavior including round-trip consistency and different hashes per view

Usage Example

// First call — no previous hash, gets the current hash
var result = await client.HasDataChangedAsync("All");
// result.HasChanged == true, result.Hash is the server's current hash

// Store result.Hash in your cache...

// Subsequent call — compare against stored hash
var check = await client.HasDataChangedAsync("All", storedHash);
if (check.HasChanged)
{
    // Download full data only when needed
    var data = await client.GetAllDataAsync();
    storedHash = check.Hash; // update stored hash
}

Backward Compatibility

This is a purely additive change:

  • New method added to ISessionizeApiClient (interface addition)
  • New DataChangedResponse DTO
  • No changes to existing methods or behavior

Adds a new HasDataChangedAsync method to ISessionizeApiClient that uses
Sessionize's built-in ?hashonly=true query parameter to fetch a lightweight
hash (~40 bytes) of the data for any view endpoint. Consumers can compare
this hash against a previously stored value to determine if a full data
download (~300KB for the All view) is necessary.

Returns a DataChangedResponse record with:
- HasChanged: whether the server hash differs from the provided hash
- Hash: the current server hash to store for subsequent checks

Includes unit tests (7) with mocked HttpClient and integration tests (6)
against the live Sessionize API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jfversluis jfversluis force-pushed the feature/has-data-changed branch from 721f60e to 97c5bd8 Compare March 30, 2026 11:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant