Skip to content

Commit

Permalink
Config RequestCacheManager for failed requests
Browse files Browse the repository at this point in the history
  • Loading branch information
jCalaU committed Apr 29, 2020
1 parent b0c18b8 commit 0916bea
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 0 deletions.
1 change: 1 addition & 0 deletions Prey/Classes/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
if PreyConfig.sharedInstance.isRegistered {
PreyNotification.sharedInstance.registerForRemoteNotifications()
TriggerManager.sharedInstance.checkTriggers()
RequestCacheManager.sharedInstance.sendRequest()
} else {
PreyDeployment.sharedInstance.runPreyDeployment()
}
Expand Down
23 changes: 23 additions & 0 deletions Prey/Classes/PreyCoreData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,27 @@ class PreyCoreData {

return fetchedObjects
}

// Get current RequestCache
func getCurrentRequestCache() -> [RequestCache] {

var fetchedObjects = [RequestCache]()
let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest()

guard let entity = NSEntityDescription.entity(forEntityName: "RequestCache", in:managedObjectContext) else {
return fetchedObjects
}

fetchRequest.entity = entity

do {
if let context = managedObjectContext {
fetchedObjects = try context.fetch(fetchRequest) as! [RequestCache]
}
} catch let error as NSError {
PreyLogger("CoreData requestCache error: \(error.localizedDescription)")
}

return fetchedObjects
}
}
16 changes: 16 additions & 0 deletions Prey/Classes/PreyHTTPClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,22 @@ class PreyHTTPClient : NSObject, URLSessionDataDelegate, URLSessionTaskDelegate
}
}

// Save on CoreData requests failed
if let err = error, (err as NSError).domain == NSURLErrorDomain, let req = task.originalRequest, let reqUrl = req.url {
// check endpoints
if reqUrl.absoluteString == (URLControlPanel+locationAwareEndpoint) || reqUrl.absoluteString == (URLControlPanel+dataDeviceEndpoint) {

// Save request
RequestCacheManager.sharedInstance.saveRequest(session.configuration, req, err)
// Delete value for sessionKey
self.requestData.removeValue(forKey:session)
self.requestCompletionHandler.removeValue(forKey:session)
// Cancel session
session.invalidateAndCancel()
return
}
}

DispatchQueue.main.async {
// Go to completionHandler
if let onCompletion = self.requestCompletionHandler[session] {
Expand Down
79 changes: 79 additions & 0 deletions Prey/Classes/RequestCacheManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,84 @@ class RequestCacheManager:NSObject {
override fileprivate init() {
}

func saveRequest(_ sessionConfig: URLSessionConfiguration, _ request: URLRequest, _ error: Error) {

// Init NSManagedObject type RequestCache
let requestCache = NSEntityDescription.insertNewObject(forEntityName: "RequestCache", into: PreyCoreData.sharedInstance.managedObjectContext)

// Check timestamp
var req = request
var requestTimestamp = CFAbsoluteTimeGetCurrent()
if let reqHeader = request.allHTTPHeaderFields, let reqTimestamp = reqHeader["Prey-timestamp"], let timestamp = Double(reqTimestamp) {
requestTimestamp = timestamp
} else {
req.addValue(String(requestTimestamp), forHTTPHeaderField:"Prey-timestamp")
}

// Set values on NSManageObject
let reqData: Data = NSKeyedArchiver.archivedData(withRootObject: req)
requestCache.setValue(reqData, forKey: "request")

let sessionConfigData: Data = NSKeyedArchiver.archivedData(withRootObject: sessionConfig)
requestCache.setValue(sessionConfigData, forKey: "session_config")

let errorData: Data = NSKeyedArchiver.archivedData(withRootObject: error)
requestCache.setValue(errorData, forKey: "error")

requestCache.setValue(requestTimestamp , forKey: "timestamp")

// Pending check requestCompletionHandler.count when > 2 and 1 fail 1 sucess ??
if PreyHTTPClient.sharedInstance.requestCompletionHandler.count == 1 {
// Save CoreData
do {
try PreyCoreData.sharedInstance.managedObjectContext.save()
} catch {
PreyLogger("Couldn't save: \(error)")
}
}
}

func sendRequest() {
let requestCacheArray = PreyCoreData.sharedInstance.getCurrentRequestCache()
guard let context = PreyCoreData.sharedInstance.managedObjectContext else {return}

// Send requests
for req in requestCacheArray {
guard let request = req.request, let sessionConfig = req.session_config, let error = req.error, let time = req.timestamp else {
context.delete(req)
return
}

guard let decodedRequest = NSKeyedUnarchiver.unarchiveObject(with: request) as? URLRequest, let decodedSession = NSKeyedUnarchiver.unarchiveObject(with: sessionConfig) as? URLSessionConfiguration, let decodedError = NSKeyedUnarchiver.unarchiveObject(with: error) as? Error else {
context.delete(req)
return
}

// Check timestamp
guard (time.doubleValue + 60*60*24) > CFAbsoluteTimeGetCurrent() else {
PreyConfig.sharedInstance.reportError(decodedError)
context.delete(req)
return
}

// Resend requests
let session = URLSession(configuration:decodedSession, delegate:PreyHTTPClient.sharedInstance, delegateQueue:nil)

// Add onCompletion to array
let onCompletion = PreyHTTPResponse.checkResponse(RequestType.dataSend, preyAction:nil, onCompletion:{(isSuccess: Bool) in PreyLogger("Request dataSend")})
PreyHTTPClient.sharedInstance.requestCompletionHandler.updateValue(onCompletion, forKey: session)

// Prepare request
PreyHTTPClient.sharedInstance.sendRequest(session, request: decodedRequest)

context.delete(req)
}

// Save CoreData
do {
try context.save()
} catch {
PreyLogger("Couldn't save: \(error)")
}
}
}

0 comments on commit 0916bea

Please sign in to comment.