Skip to content

Task 8 — Add HttpConfigSource with ETag caching and robust fetch semantics#11

Open
KostasBan wants to merge 2 commits into
developmentfrom
codex/add-httpconfigsource-with-etag-caching
Open

Task 8 — Add HttpConfigSource with ETag caching and robust fetch semantics#11
KostasBan wants to merge 2 commits into
developmentfrom
codex/add-httpconfigsource-with-etag-caching

Conversation

@KostasBan

Copy link
Copy Markdown
Owner

Motivation

  • Provide a production-style remote config fetcher that integrates with existing repository abstractions and supports HTTP caching semantics (ETag / 304) for efficient refreshes.
  • Ensure repository refresh semantics do not overwrite the last-known-good on no-change (304), fetch failures, or invalid payloads and only persist/emit changes for real updates.

Description

  • Added Packages/com.kbanakakis.beacon/Runtime/Repositories/HttpConfigSource.cs implementing IConfigSource using UnityWebRequest with configurable timeout, retry count, exponential backoff, optional static headers, optional dynamic header provider, and in-memory ETag caching; FetchAsync sends If-None-Match, treats 304 as Success=true, Bytes=null, and returns ETag (or Last-Modified) as SourceVersion on 200.
  • Updated DefaultConfigRepository.RefreshAsync to treat Success=true with Bytes==null as no-change (do not persist or fire SnapshotChanged) and added HasNoMaterialChange to avoid persisting/emitting when version/schema/bytes are identical.
  • Expanded Packages/com.kbanakakis.beacon/Tests/RepositorySmokeTests.cs with NUnit tests covering: successful 200 update + persistence, 304/no-bytes -> treated as no-change, fetch failure preserves stored snapshot, and invalid payload preserves last-known-good; also added SequenceConfigSource and enhanced FakeConfigStore test helpers.
  • Added an asm/metadata file for the new HttpConfigSource (HttpConfigSource.cs.meta) and a small fix to use _url.AbsoluteUri when creating the request.

Testing

  • Attempted to run the NUnit test suite with dotnet test, but the automated attempt failed because dotnet is not installed in this environment (command not found), so no tests were executed here.

Codex Task

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 63355d7341

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +56 to +58
if (fetchResult.Bytes == null)
{
return new RefreshResult(false, null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Treat null payload as error when snapshot is empty

The new Bytes == null branch returns Changed=false with no error for all successful fetches, but that is only safe when a last-known-good payload already exists. On a fresh repository (or after load failure), this path silently reports success while leaving the snapshot empty, so callers never get a usable config and have no error to act on. Gate this no-change path on existing snapshot bytes and return a failure when there is nothing cached locally.

Useful? React with 👍 / 👎.

for (var attempt = 0; attempt <= _retryCount; attempt++)
{
ct.ThrowIfCancellationRequested();
var result = await FetchOnceAsync(ct).ConfigureAwait(false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep retry loop on the original synchronization context

FetchAsync uses ConfigureAwait(false) inside the retry loop, so after the first failed attempt subsequent retries can run without the original synchronization context. FetchOnceAsync then polls operation.isDone via repeated await Task.Yield(), which becomes a tight reschedule loop off-context and can burn CPU during slow/failing requests (the exact scenario where retries happen). Preserve context for retry iterations, or use a non-spin completion mechanism.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant