Skip to content

Snapshot Support - #60

Open
zhiyuanliang-ms wants to merge 9 commits into
mainfrom
zhiyuanliang/snapshot
Open

Snapshot Support#60
zhiyuanliang-ms wants to merge 9 commits into
mainfrom
zhiyuanliang/snapshot

Conversation

@zhiyuanliang-ms

@zhiyuanliang-ms zhiyuanliang-ms commented Nov 30, 2025

Copy link
Copy Markdown
Member

Why this PR?

Support the snapshot APIs.

Snapshot storage

  • Metadata: All snapshot metadata persisted as newline-delimited JSON records in .aace/snapshot.ndjson. New snapshot uses Append; update/remove rewrites whole file via temp file + atomic Replace.
  • Content: Each snapshot’s captured key-values serialized as NDJSON into its own file (snapshotId.ndjson) under .aace/snapshots folder.

Snapshot management

  • Provision: On snapshot Create, the emulator immediately gathers matching key-values, writes the content NDJSON file, computes media info (size, hash, etag), and then appends the snapshot metadata in one flow. A successful PUT request returns a snapshot already in Ready state (no intermediate Provisioning state). This is different from the async provision behavior of the real App Config service.
  • Clean up (lazy deletion): Purge only runs once, triggered inside SnapshotProvider.EnsureInit after loading metadata cache. (Different from KeyValueProvider's periodic cleanup logic)

// front. Re-query to get the fully-provisioned snapshot to return.
Snapshot created = (await _provider.Get(new SnapshotSearchOptions
{
Name = SearchQuery.Escape(name),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The snapshot name passed from the controller parameter is escaped or not? Why the name using in create method is not escaped, but it is escaped here?

@zhiyuanliang-ms zhiyuanliang-ms Jul 22, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The snapshot name passed from the controller parameter is escaped or not?

No. It is literal.

Why the name using in create method is not escaped, but it is escaped here?

This is actually a good catch. First thing, store unescaped name is the bahavior of real app config service.

But using escaped name for search is actually a bug in emulator. This bug also exists in the kv controller.

For example, if we put a key: my*key, it will be stored literally. But when we get it through /kv/my*key, it will return 404 instead of 200.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in #99

Comment thread src/Azure.AppConfiguration.Emulator.Tenant/TenantOptions.cs
public sealed class SnapshotProvider : ISnapshotProvider
public sealed class SnapshotProvider :
ISnapshotProvider,
IHostedService,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

SnapshotProvider also runs as a backgroud hosted service, is this intentional?Maybe isolate the hosted servivce from the provider is better

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is intentional. I refered to KeyValueProvider. The StartAsync will warm the cache and purge the archieved snapshot

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.

3 participants