CloudKit: empêcher les loggings en double

Je travaille à travers une application qui tire datatables d'un service Web externe dans une database privée CloudKit. L'application est une application user unique, mais je cours dans une condition de course que je ne suis pas sûr de savoir comment éviter.

Chaque logging de mes données externes possède un identifiant unique que je mappe à mes instances CKRecord. Le stream de démarrage général de l'application est le suivant:

  1. Récupère les CKRecords actuels pour le type d'logging concerné.
  2. Récupère les loggings externes.
  3. Pour chaque logging externe, s'il n'existe pas dans CloudKit, créez-le via batch create (opération de modification).

Maintenant, le problème est, si ce process est lancé sur deux des dispositifs d'un user simultanément, puisque le CK et le fetch externe est asynchronous, il y a une forte possibilité que je vais get des loggings en double.

Je sais que je peux utiliser des zones pour valider atomiquement toutes mes instances CKRecord, mais je ne pense pas que cela résout mon problème car si toutes ces extractions se produisent à la même heure, la sauvegarde n'est pas vraiment le problème.

Mes questions sont:

  1. Est-ce que quelqu'un sait d'un moyen de "verrouiller" la database privée pour les écritures sur tous les appareils d'un user?
  2. Sinon, existe-t-il un moyen d'imposer l'unicité dans n'importe quel champ CKRecord?
  3. Ou, est-il un moyen d'utiliser une valeur personnalisée comme key primaire, dans ce cas, je pourrais utiliser mon ID externe comme ID CK et permettre au système d'éviter les duplicates lui-même.

Merci pour l'aide à l'avance!

Réponses:

  1. Non, vous ne pouvez pas verrouiller la database privée
  2. Cloudkit applique déjà et assume l'unicité de votre ID d'logging
  3. Vous pouvez faire l'ID d'logging comme vous le souhaitez (dans la partie non-zone de celui-ci).

Explication:

En ce qui concerne votre problème de duplication. Si vous êtes celui qui crée les identifiants d'logging (à partir des loggings externes que vous avez mentionnés par exemple), alors au pire, vous devriez avoir un logging sur l'autre avec les mêmes données si vous avez une condition de concurrency. Je ne pense pas que ce soit un problème pour le cas extrême deux appareils lancent ce process en même time. Fondamentalement, votre logique d'aller chercher d'abord des loggings existants et de les modifier me semble bien.

Code:

//employeeID is a unique ID to identify an employee let employeeID = "001" //Remember the recordID needs to be unique within the same database. //Assuming you have different record types, it is better to prefix the record name with the record type so that it is unique let recordName = "Employee-\(employeeID)" //If you are using a custom zone let customZoneID = CKRecordZoneID(zoneName: "SomeCustomZone", ownerName: CKCurrentUserDefaultName) let recordIDInCustomZone = CKRecordID(recordName: recordName, zoneID: customZoneID) //If you are using the default zone let recordIDInDefaultZone = CKRecordID(recordName: recordName) 

J'ai eu le même problème de duplicates téléchargés lorsque j'ai essayé de lire dans une database de plus de 100 loggings; la solution se trouve dans l'exemple Atlas d'Apple qui utilise un boolean pour vérifier si le dernier process a été terminé avant le lancement du suivant. Vous trouvez un bloc un peu comme ça …

 @synchronized (self) { // Quickly returns if another loadNextBatch is running or we have the oldest post if(self.isLoadingBatch || self.haveOldestPost) return; else self.isLoadingBatch = YES; } 

Incidemment, ici le code pour créer votre propre key d'logging.

 CKRecordID *customID = [[CKRecordID alloc] initWithRecordName: [globalEOConfirmed returnEOKey:i]]; newrecord = [[CKRecord alloc] initWithRecordType:@"Blah" recordID:customID];