debugSnapshot method

Future<Map<String, Object?>> debugSnapshot({
  1. int sampleKeyLimit = 20,
})

Builds a JSON-safe snapshot of the cache's live internal state for debugging and diagnostics.

The returned map contains:

  • watchers: every registered watch stream (value and meta), with its key, the policy it will be refetched with, and its TTL.
  • inFlightFetches: keys with a deduplicated fetch currently running.
  • pendingMutations: the offline mutation queue — id, key, status, retry count, last error (stringified), and enqueue time.
  • stats: the SyncacheStats counters (see stats).
  • store: the approximate entry count and up to sampleKeyLimit sample keys, or null when the store cannot enumerate keys.

Every value is a JSON primitive, list, or map, so the result can be logged directly or piped through jsonEncode — or use SyncacheDebug for a ready-made facade. This is a diagnostic aid: the shape is not a stable API contract and may grow over time.

Implementation

Future<Map<String, Object?>> debugSnapshot({int sampleKeyLimit = 20}) async {
  _checkNotDisposed();

  final watchers = <Map<String, Object?>>[
    for (final registration in _watchers.values)
      {
        'key': registration.key,
        'kind': 'value',
        'policy': registration.policy.name,
        'ttlMs': registration.ttl?.inMilliseconds,
      },
    for (final registration in _metaWatchers.values)
      {
        'key': registration.key,
        'kind': 'meta',
        'policy': registration.policy.name,
        'ttlMs': registration.ttl?.inMilliseconds,
      },
  ];

  final pendingMutations = <Map<String, Object?>>[
    for (final info in _mutationQueue.snapshot)
      {
        'id': info.id,
        'key': info.key,
        'status': info.status.name,
        'retryCount': info.retryCount,
        'queuedAt': info.queuedAt.toIso8601String(),
        'lastAttemptAt': info.lastAttemptAt?.toIso8601String(),
        'lastError': info.lastError?.toString(),
      },
  ];

  Map<String, Object?>? storeInfo;
  if (store is IterableStore<T>) {
    try {
      final keys = await (store as IterableStore<T>).keys();
      storeInfo = {
        'entryCount': keys.length,
        'sampleKeys': keys.take(sampleKeyLimit).toList(growable: false),
      };
    } catch (_) {
      storeInfo = null;
    }
  }

  return {
    'watchers': watchers,
    'inFlightFetches': _fetchEngine.inFlightKeys,
    'pendingMutations': pendingMutations,
    'stats': (await stats).toDebugJson(),
    'store': storeInfo,
  };
}