persist method

  1. @override
Future<void> persist(
  1. List<Document> docs
)
override

Persist function called with the bath of documents that have changed (including been deleted) within the last throttle window specified by the Persistor.persistenceThrottle duration.

Implementation

@override
persist(docs) async {
  // The updated persistence keys for documents are built into a local resolver
  // passed to the worker. This has two main benefits:
  // 1. It pre-computes the resolved persistence keys across the document updates, eliminating conflicts.
  //    Ex. If an update to users__1__friends__1 which resolves to persistence key "users" at resolver path "users"
  //        is followed a subsequent update to users__1 that changes the persistence key at resolver path "users" to "other_users",
  //        then the previous update to users__1__friends__1 would have an inaccurate persistence key.

  //    Pre-computing the local resolver ensures that all documents can lookup accurate persistence keys.
  //    were not pre-computed in this way, then there could be conflicts between the changes documents make
  //
  // 2. It de-duplicates persistence keys. If there are many documents that all roll up
  //    to a given key, then the key is only specified once in the local resolver rather than
  //    being duplicated and sent independently with each document.
  final resolver = ValueStore<String>();
  final List<FilePersistDocument> persistDocs = [];
  final globalPersistorSettings = Loon.persistorSettings;

  final defaultKey = switch (globalPersistorSettings) {
    FilePersistorSettings(key: FilePersistorValueKey key) => key,
    _ => FilePersistor.defaultKey,
  };
  resolver.write(ValueStore.root, defaultKey.value);

  for (final doc in docs) {
    bool encrypted = false;
    final persistorSettings = doc.persistorSettings;

    if (persistorSettings != null) {
      final persistorDoc = persistorSettings.doc;
      final docSettings = persistorSettings.settings;

      encrypted =
          docSettings is FilePersistorSettings && docSettings.encrypted;

      switch (docSettings) {
        case FilePersistorSettings(key: FilePersistorValueKey key):
          String path;

          /// A value key is stored at the parent path of the document unless it is a document
          /// on the root collection via [Loon.doc], which should store keys under its own path.
          if (persistorDoc.parent != Collection.root.path) {
            path = persistorDoc.parent;
          } else {
            path = persistorDoc.path;
          }

          resolver.write(path, key.value);

          break;
        case FilePersistorSettings(key: FilePersistorBuilderKey keyBuilder):
          final snap = persistorDoc.get();
          final path = persistorDoc.path;

          if (snap != null) {
            resolver.write(path, (keyBuilder as dynamic)(snap));
          }

          break;
      }
    } else if (globalPersistorSettings is FilePersistorSettings) {
      encrypted = globalPersistorSettings.encrypted;

      switch (globalPersistorSettings) {
        case FilePersistorSettings(key: FilePersistorBuilderKey keyBuilder):
          final snap = doc.get();
          final path = doc.path;

          if (snap != null) {
            resolver.write(path, (keyBuilder as dynamic)(snap));
          }
          break;
        default:
          break;
      }
    }

    persistDocs.add(
      FilePersistDocument(
        path: doc.path,
        data: doc.getSerialized(),
        encrypted: encrypted,
      ),
    );
  }

  await _sendMessage(
    PersistMessageRequest(resolver: resolver, docs: persistDocs),
  );
}