Skip to content

fix: prune orphaned DataStore keys after the key-shape change #78

Description

@MaxMichel2

Part of #72

Depends on #2, #4.

Summary

The DataStore key shape changes twice in this migration — EndpointKey.compositeKey drops environmentId (#2: 3-tuple → 2-tuple) and OperationMockState.Mock's persisted payload changes from a file-name string to a (statusCode, exampleName) pair (#4). Every existing network_mock_endpoint_* DataStore entry written by a pre-0.2.0 version of this library will be orphaned by both changes. Nothing currently prunes unknown keys, so they accumulate forever.

Current state

MockStateRepository (devview-networkmock-core/src/commonMain/kotlin/com/worldline/devview/networkmock/core/repository/MockStateRepository.kt) stores three kinds of DataStore entries:

  • network_mock_global_enabled (Boolean) — unaffected by this migration
  • network_mock_last_modified (Long) — unaffected
  • network_mock_endpoint_{compositeKey} (String, JSON-encoded EndpointMockState) — one per operation, keyed by the old 3-tuple composite key (:47-49, key construction at :150-154)

observeState() (:179-213) rebuilds NetworkMockState on every emission by scanning all preference keys with the network_mock_endpoint_ prefix (:190) and JSON-decoding each value, falling back to EndpointMockState.Network on any decode failure (:196-206). This fallback already exists for corrupt data — but a key whose name no longer corresponds to any current operation isn't corrupt, it's just orphaned, and it will sit in DataStore forever taking up space and showing up in preferences.asMap() scans.

What to build

A one-shot migration step, run once on first load after upgrading to 0.2.0, that removes DataStore entries under the old key shape. Two reasonable approaches — pick whichever is simpler given how #2/#4 actually land:

  1. Version-gated wipe: store a small network_mock_schema_version preference; if it's absent or lower than the current schema version, clear all network_mock_endpoint_* entries once, then write the new schema version. Simplest, loses previously-selected mocks across the upgrade (acceptable — this is dev-tooling state, not user data, and the alternative is silently-wrong state from misparsed old keys).
  2. Best-effort key translation: parse old-shape keys ({groupId}-{environmentId}-{endpointId} and old Mock(responseFile) payloads) and translate them to the new shape/payload where possible, dropping what can't be translated. More user-friendly, meaningfully more code and test surface for a one-time dev-tool state migration.

Recommend option 1 given the stakes (this is disabled-by-default developer tooling state, not user data) — but note the tradeoff explicitly in the PR if a different call is made.

Acceptance criteria

  • After upgrading from a pre-0.2.0 build, no network_mock_endpoint_* key written under the old 3-tuple shape remains in DataStore after the app has launched once.
  • The migration runs exactly once (idempotent — running it again on an already-migrated store is a no-op).
  • network_mock_global_enabled and network_mock_last_modified are untouched by the migration.
  • A test simulates a pre-migration DataStore (old-shape keys seeded via FakePreferencesDataStore, from devview-test) and asserts the post-migration state is clean.
  • This is called out prominently in the migration guide (⬆️ Update all dependencies #9) — DataStore state, not just the config file, changes shape across this upgrade.

Files likely touched

  • devview-networkmock-core/src/commonMain/kotlin/com/worldline/devview/networkmock/core/repository/MockStateRepository.kt
  • devview-networkmock-core/src/commonTest/kotlin/com/worldline/devview/networkmock/core/repository/MockStateRepositoryTest.kt

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions