2014-06-11 15 views
5

I documenti ufficiali parlano della coerenza di CloudKit? Secondo le mie prove sembra essere finalmente coerente - la lettura di un disco subito dopo la scrittura potrebbe funzionare e non potrebbe (di restituire i risultati vuoto):CloudKit è fortemente coerente o coerente?

CKDatabase *database = [[CKContainer defaultContainer] publicCloudDatabase]; 
CKRecord *record = [[CKRecord alloc] initWithRecordType:@"Foo"]; 

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 
[database saveRecord:record completionHandler:^(CKRecord *record, NSError *error) { 
    CKQuery *query = [[CKQuery alloc] initWithRecordType:@"Foo" predicate:[NSPredicate predicateWithFormat:@"TRUEPREDICATE"]]; 
    [database performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) { 
     XCTAssertEqualObjects(results, @[], @"Freshly written object not returned by query."); // succeeds 
     dispatch_semaphore_signal(semaphore); 
    }]; 
}]; 

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 

C'è un modo per forzare una lettura fortemente coerente che riflettesse tutto aggiornamenti precedenti?

+0

Sto notando la stessa cosa nei miei test. Sto salvando un record e aspetto che si completi con successo. Se poi eseguo una query per tutti i record, il mio nuovo record non viene restituito. Hai trovato qualche informazione affermando che CloudKit è alla fine coerente? –

+0

Il mio caso d'uso era fortunatamente molto semplice, quindi ho "risolto" il problema con una sorta di cache nel livello del datastore: quando un elemento viene inserito nell'archivio dati, viene scritto su iCloud _e_ memorizzato sul client per un breve periodo. E quando il livello del datastore viene interrogato, aggiunge i record della cache vivente al set di risultati. Stupido, ma funziona. – zoul

+1

@zoul mai trovato un modo migliore per gestire questo? L'ultima parte del commento in linea in CKModifyRecordsOperation.h per modifyRecordsCompletionBlock suggerisce che questo è il comportamento progettato: "** Questa chiamata si verifica non appena il server ha visto tutte le modifiche ai record e può essere richiamato mentre il server sta elaborando il lato effetti di tali modifiche. ** " – George

risposta

0

La mia unica esperienza con il termine "coerenza finale" deriva dall'uso di CouchDB, che alla fine è coerente. CloudKit è molto diverso da CouchDB in quanto CouchDB consente la replica di database distribuiti, mentre CloudKit fornisce solo "servizi per la gestione del trasferimento di dati da e verso i server iCloud" - è solo un meccanismo di trasporto.

Sono abbastanza sicuro che il meccanismo di trasporto non sia alla fine coerente: salva e recupera direttamente dal server CloudKit.

Poiché CloudKit è solo un meccanismo di trasporto, sei responsabile della gestione della cache/database locale. Il tuo database locale sarà considerato alla fine coerente, perché non è necessariamente coerente tra le sincronizzazioni e diventa coerente quando alla fine lo si sincronizza con CloudKit.

Ora, si dice che nei test si sta salvando e quindi si sta tentando di recuperare un record. Ma ho notato nel tuo codice che non stai controllando gli errori nell'operazione di salvataggio. Quindi, forse c'è un errore durante il salvataggio che ti manca?

+0

Non so sull'infrastruttura iCloud di Apple, ma ho il sospetto che ci siano molti diversi server iCloud in esecuzione dietro un qualche tipo di schema di bilanciamento del carico.Quindi sembra del tutto possibile che una chiamata per salvare un record possa essere indirizzata a un'istanza del server mentre una chiamata successiva viene instradata a un'altra istanza. A seconda di quanto bene iCloud mantiene tali istanze in sincronia, avere un modello di coerenza finale potrebbe essere abbastanza ragionevole aspettarsi qui. –

7

È un po 'di entrambi: CloudKit è fortemente coerente se si recupera un record per identificatore, ma alla fine è coerente quando si recupera un record con una query.

Quando un CKModifyRecordsOperation restituisce correttamente il record è immediatamente rilevabile dal suo identificatore.

Tuttavia, il server impiega del tempo per analizzare i valori del record e aggiornare e distribuire gli indici di ricerca. Fino a quando l'indicizzazione non sarà completata, non vedrai il record in nessuna query.