Skip to content

Commit ac779bb

Browse files
SK-2589 handle insert callback separately
1 parent 0d80511 commit ac779bb

6 files changed

Lines changed: 392 additions & 7 deletions

File tree

Sources/Skyflow/collect/CollectContainer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public extension Container {
9999
onFailureHandler: {
100100
}
101101
)
102-
self.skyflow.apiClient.post(records: records!, callback: logCallback, options: icOptions, contextOptions: tempContextOptions)
102+
self.skyflow.apiClient.postAndUpdate(records: records!, callback: logCallback, options: icOptions, contextOptions: tempContextOptions)
103103
}
104104
}
105105

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* Copyright (c) 2022 Skyflow
3+
*/
4+
5+
// Callback used while API callback for Collect the elements
6+
7+
import Foundation
8+
import UIKit
9+
10+
internal class InsertAPICallback: Callback {
11+
var apiClient: APIClient
12+
var records: [String: Any]
13+
var callback: Callback
14+
var options: ICOptions
15+
var contextOptions: ContextOptions
16+
17+
internal init(callback: Callback, apiClient: APIClient, records: [String: Any], options: ICOptions, contextOptions: ContextOptions) {
18+
self.records = records
19+
self.apiClient = apiClient
20+
self.callback = callback
21+
self.options = options
22+
self.contextOptions = contextOptions
23+
}
24+
internal func onSuccess(_ responseBody: Any) {
25+
guard let url = URL(string: self.apiClient.vaultURL + self.apiClient.vaultID) else {
26+
self.callback.onFailure(ErrorCodes.INVALID_URL().getErrorObject(contextOptions: self.contextOptions))
27+
return
28+
}
29+
30+
do {
31+
let (request, session) = try self.getRequestSession(url: url)
32+
33+
34+
let task = session.dataTask(with: request) { data, response, error in
35+
do {
36+
let response = try self.processResponse(data: data, response: response, error: error)
37+
self.callback.onSuccess(response)
38+
} catch {
39+
self.callback.onFailure(error)
40+
}
41+
}
42+
task.resume()
43+
} catch let error {
44+
self.callback.onFailure(error)
45+
return
46+
}
47+
}
48+
49+
internal func onFailure(_ error: Any) {
50+
self.callback.onFailure(error)
51+
}
52+
53+
internal func buildFieldsDict(dict: [String: Any]) -> [String: Any] {
54+
var temp: [String: Any] = [:]
55+
for (key, val) in dict {
56+
if let v = val as? [String: Any] {
57+
temp[key] = buildFieldsDict(dict: v)
58+
} else {
59+
temp[key] = val
60+
}
61+
}
62+
return temp
63+
}
64+
internal func getRequestSession(url: URL) throws -> (URLRequest, URLSession) {
65+
var jsonString = ""
66+
67+
do {
68+
let deviceDetails = FetchMetrices().getMetrices()
69+
let jsonData = try JSONSerialization.data(withJSONObject: deviceDetails, options: [])
70+
jsonString = String(data: jsonData, encoding: .utf8) ?? ""
71+
} catch {
72+
jsonString = ""
73+
}
74+
var request = URLRequest(url: url)
75+
request.httpMethod = "POST"
76+
77+
do {
78+
let data = try JSONSerialization.data(withJSONObject: self.apiClient.constructBatchRequestBody(records: self.records, options: options))
79+
request.httpBody = data
80+
}
81+
82+
request.setValue(("Bearer " + self.apiClient.token), forHTTPHeaderField: "Authorization")
83+
request.setValue(jsonString, forHTTPHeaderField: "sky-metadata")
84+
85+
return (request, URLSession(configuration: .default))
86+
87+
}
88+
89+
func processResponse(data: Data?, response: URLResponse?, error: Error?) throws -> [String: Any] {
90+
if error != nil || response == nil {
91+
throw error!
92+
}
93+
94+
if let httpResponse = response as? HTTPURLResponse {
95+
let range = 400...599
96+
if range ~= httpResponse.statusCode {
97+
var description = "Insert call failed with the following status code" + String(httpResponse.statusCode)
98+
var errorObject: Error = ErrorCodes.APIError(code: httpResponse.statusCode, message: description).getErrorObject(contextOptions: self.contextOptions)
99+
100+
if let safeData = data {
101+
do {
102+
let desc = try JSONSerialization.jsonObject(with: safeData, options: .allowFragments) as! [String: Any]
103+
let error = desc["error"] as! [String: Any]
104+
description = error["message"] as! String
105+
if let requestId = httpResponse.allHeaderFields["x-request-id"] {
106+
description += " - request-id: \(requestId)"
107+
}
108+
errorObject = ErrorCodes.APIError(code: httpResponse.statusCode, message: description).getErrorObject(contextOptions: self.contextOptions)
109+
} catch {
110+
errorObject = ErrorCodes.APIError(code: httpResponse.statusCode, message: String(data: safeData, encoding: .utf8)!).getErrorObject(contextOptions: self.contextOptions)
111+
}
112+
}
113+
throw errorObject
114+
}
115+
}
116+
117+
guard let safeData = data else {
118+
return [:]
119+
}
120+
121+
return try getCollectResponseBody(data: safeData)
122+
123+
}
124+
125+
func getCollectResponseBody(data: Data) throws -> [String: Any]{
126+
let originalString = String(decoding: data, as: UTF8.self)
127+
let changedData = Data(originalString.utf8)
128+
let jsonData = try JSONSerialization.jsonObject(with: changedData, options: .allowFragments) as! [String: Any]
129+
var responseEntries: [Any] = []
130+
131+
let receivedResponseArray = (jsonData[keyPath: "responses"] as! [Any])
132+
133+
let inputRecords = self.records["records"] as! [Any]
134+
135+
let length = inputRecords.count
136+
for (index, _) in inputRecords.enumerated() {
137+
var tempEntry: [String: Any] = [:]
138+
tempEntry["table"] = (inputRecords[index] as! [String: Any])["table"]
139+
if self.options.tokens {
140+
let fieldsDict = (receivedResponseArray[length + index] as! [String: Any])["fields"]
141+
if fieldsDict != nil {
142+
let fieldsData = try JSONSerialization.data(withJSONObject: fieldsDict!)
143+
let fieldsObj = try JSONSerialization.jsonObject(with: fieldsData, options: .allowFragments)
144+
tempEntry["fields"] = self.buildFieldsDict(dict: fieldsObj as? [String: Any] ?? [:])
145+
tempEntry[keyPath: "fields.skyflow_id"] = (((receivedResponseArray[index] as! [String: Any])["records"] as! [Any])[0] as! [String: Any])["skyflow_id"]
146+
}
147+
} else {
148+
tempEntry["skyflow_id"] = (((receivedResponseArray[index] as! [String: Any])["records"] as! [Any])[0] as! [String: Any])["skyflow_id"]
149+
}
150+
responseEntries.append(tempEntry)
151+
}
152+
153+
return ["records": responseEntries]
154+
155+
}
156+
}

Sources/Skyflow/composable/ComposableContainer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ public extension Container {
283283
onFailureHandler: {
284284
}
285285
)
286-
self.skyflow.apiClient.post(records: records!, callback: logCallback, options: icOptions, contextOptions: tempContextOptions)
286+
self.skyflow.apiClient.postAndUpdate(records: records!, callback: logCallback, options: icOptions, contextOptions: tempContextOptions)
287287
}
288288
}
289289

Sources/Skyflow/core/APIClient.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,14 @@ internal class APIClient {
5959
}
6060
}
6161

62-
internal func post(records: [String: Any], callback: Callback, options: ICOptions, contextOptions: ContextOptions) {
62+
internal func postAndUpdate(records: [String: Any], callback: Callback, options: ICOptions, contextOptions: ContextOptions) {
6363
let collectApiCallback = CollectAPICallback(callback: callback, apiClient: self, records: records, options: options, contextOptions: contextOptions)
6464
self.getAccessToken(callback: collectApiCallback, contextOptions: contextOptions)
6565
}
66+
internal func post(records: [String: Any], callback: Callback, options: ICOptions, contextOptions: ContextOptions) {
67+
let insertApiCallback = InsertAPICallback(callback: callback, apiClient: self, records: records, options: options, contextOptions: contextOptions)
68+
self.getAccessToken(callback: insertApiCallback, contextOptions: contextOptions)
69+
}
6670
internal func constructUpdateRequestBody(records: [String: Any], options: ICOptions) -> [String: Any] {
6771
var postPayload: [String : Any] = [:]
6872
var fields: [String: Any] = [:]

Tests/LinuxMain.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import XCTest
77
var tests = [XCTestCaseEntry]()
88
tests += skyflow_iOS_collectTests.allTests()
99
tests += skyflow_iOS_revealTests.allTests()
10-
test += skyflow_iOS_errorTests.allTests()
11-
test += skyflow_iOS_getByIdTests.allTests()
12-
test += skyflow_iOS_elementTests.allTests()
13-
test += skyflow_iOS_utilTests.allTests()
10+
tests += skyflow_iOS_errorTests.allTests()
11+
tests += skyflow_iOS_getByIdTests.allTests()
12+
tests += skyflow_iOS_elementTests.allTests()
13+
tests += skyflow_iOS_utilTests.allTests()
1414
XCTMain(tests)

0 commit comments

Comments
 (0)