ioscloudkitckquery

CKQuery fails when returning large set


I am using CloudKit to download files when an app is launched. I have a CKQuery that finds all files not yet downloaded. It works fine when there are only one or two to download, but when there are a large number, it fails with the error:

\"Server Rejected Request\" (15/2000); server message = \"Internal server error\";

This happens on a device or simulator.

Relevant code

    let container = CKContainer(identifier: "iCloud.quaritate.Agni")
    let publicDB = container.publicCloudDatabase
    let privateDB = container.privateCloudDatabase

    let predicate = NSPredicate(format: "NOT (%@ CONTAINS Name)", downloadedTitles)
    let query = CKQuery(recordType: "List", predicate: predicate)
    publicDB.performQuery(query, inZoneWithID: nil, completionHandler: {
        results, error in
        if error != nil{
            //error getting lists
            NSLog("\(error?.description)")
        }else{
            //got lists
        }
    }

EDIT
I have updated my code to use CKOperationQueue

func getNewWords(){
    let predicate = NSPredicate(format: "NOT (%@ CONTAINS Name)", downloadedTitles)
    let query = CKQuery(recordType: "List", predicate: predicate)

    let queryOperation = CKQueryOperation(query: query)
    let operationQueue = NSOperationQueue()
    self.executeQueryOperation(queryOperation, onOperationQueue: operationQueue)
}

func executeQueryOperation(queryOperation: CKQueryOperation, onOperationQueue operationQueue: NSOperationQueue) {
    NSLog("Executing query operation")
    let container = CKContainer(identifier: "iCloud.quaritate.Agni")
    let publicDB = container.publicCloudDatabase

    queryOperation.database = publicDB

    queryOperation.recordFetchedBlock = {(record:CKRecord) in
        self.saveRecord(record)
    }

    queryOperation.queryCompletionBlock = {(cursor:CKQueryCursor?, error:NSError?)->Void in
        guard error == nil else{
            NSLog("Query error: \(error?.description)")
            return
        }
        if let queryCursor = cursor { //there are more operations to execute
            let queryCursorOperation = CKQueryOperation(cursor: queryCursor)
            self.executeQueryOperation(queryCursorOperation, onOperationQueue: operationQueue)
        }
    }
    operationQueue.addOperation(queryOperation)
}

But still receive the same error.


Solution

  • Double-check that downloadedTitles is not an empty array. The server will return this error if an empty array is sent in a query like this.

    This is a poor error from the server- I've filed a bug to have a better error message (or simply no results) returned in this case.