Skip to content

Commit c3103b4

Browse files
feat: Custom dictionaries (#717)
* Implement Dictionary commands and models * Implement dictionary methods * Implement all methods and commands tests * Waitable components refactoring to support application-related wait * Improve HTTPRequester implementation logging
1 parent 722750b commit c3103b4

39 files changed

+1340
-135
lines changed

Sources/AlgoliaSearchClient/Async/WaitTask.swift

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ import Foundation
99

1010
class WaitTask: AsyncOperation, ResultContainer {
1111

12-
typealias TaskIDProvider = () -> TaskID?
12+
typealias TaskStatusService = (RequestOptions?, @escaping ResultCallback<TaskInfo>) -> Void
1313

14-
let index: Index
15-
let taskIDProvider: TaskIDProvider
14+
let taskStatusService: TaskStatusService
1615
let requestOptions: RequestOptions?
1716
let timeout: TimeInterval?
1817
private var launchDate: Date?
@@ -32,25 +31,11 @@ class WaitTask: AsyncOperation, ResultContainer {
3231
return Date().timeIntervalSince(launchDate) >= timeout
3332
}
3433

35-
init(index: Index,
36-
taskIDProvider: @autoclosure @escaping TaskIDProvider,
34+
init(taskStatusService: @escaping TaskStatusService,
3735
timeout: TimeInterval? = nil,
3836
requestOptions: RequestOptions?,
3937
completion: @escaping ResultCallback<TaskStatus>) {
40-
self.index = index
41-
self.taskIDProvider = taskIDProvider
42-
self.timeout = timeout
43-
self.requestOptions = requestOptions
44-
self.completion = completion
45-
}
46-
47-
init(index: Index,
48-
taskID: TaskID,
49-
timeout: TimeInterval? = nil,
50-
requestOptions: RequestOptions?,
51-
completion: @escaping ResultCallback<TaskStatus>) {
52-
self.index = index
53-
self.taskIDProvider = { return taskID }
38+
self.taskStatusService = taskStatusService
5439
self.timeout = timeout
5540
self.requestOptions = requestOptions
5641
self.completion = completion
@@ -70,12 +55,7 @@ class WaitTask: AsyncOperation, ResultContainer {
7055
return
7156
}
7257

73-
guard let taskID = taskIDProvider() else {
74-
result = .failure(Error.missingTaskID)
75-
return
76-
}
77-
78-
index.taskStatus(for: taskID, requestOptions: requestOptions) { [weak self] result in
58+
taskStatusService(requestOptions) { [weak self] result in
7959
guard let request = self else { return }
8060

8161
switch result {
@@ -97,20 +77,29 @@ class WaitTask: AsyncOperation, ResultContainer {
9777

9878
enum Error: Swift.Error {
9979
case timeout
100-
case missingTaskID
10180
}
10281

10382
}
10483

10584
extension WaitTask {
10685

10786
convenience init(index: Index,
108-
task: Task,
87+
taskID: TaskID,
88+
timeout: TimeInterval? = nil,
89+
requestOptions: RequestOptions?,
90+
completion: @escaping ResultCallback<TaskStatus>) {
91+
self.init(taskStatusService: { requestOptions, completion in index.taskStatus(for: taskID, requestOptions: requestOptions, completion: completion) },
92+
timeout: timeout,
93+
requestOptions: requestOptions,
94+
completion: completion)
95+
}
96+
97+
convenience init(client: Client,
98+
taskID: AppTaskID,
10999
timeout: TimeInterval? = nil,
110100
requestOptions: RequestOptions?,
111101
completion: @escaping ResultCallback<TaskStatus>) {
112-
self.init(index: index,
113-
taskID: task.taskID,
102+
self.init(taskStatusService: { requestOptions, completion in client.taskStatus(for: taskID, requestOptions: requestOptions, completion: completion) },
114103
timeout: timeout,
115104
requestOptions: requestOptions,
116105
completion: completion)

Sources/AlgoliaSearchClient/Client/AccountClient.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ public struct AccountClient {
8484
waitSettings
8585
].map(\.task) + waitObjects.batchesResponse.tasks
8686

87-
let waitService = WaitService(taskIndices: tasks.map { (destination, $0.taskID) })
88-
return WaitableWrapper(wrapped: tasks, waitService: waitService)
87+
return WaitableWrapper(tasks: tasks, index: destination)
8988
}
9089

9190
}
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
//
2+
// SearchClient+Dictionaries.swift
3+
//
4+
//
5+
// Created by Vladislav Fitc on 21/01/2021.
6+
//
7+
8+
import Foundation
9+
10+
public extension SearchClient {
11+
12+
// MARK: - Save dictionary entries
13+
14+
/**
15+
Save dictionary entries
16+
17+
- Parameter dictionary: Target dictionary
18+
- Parameter dictionaryEntries: List of dictionary entries
19+
- Parameter requestOptions: Configure request locally with RequestOptions
20+
- Parameter completion: Result completion
21+
- Returns: Launched asynchronous operation
22+
*/
23+
@discardableResult func saveDictionaryEntries<D: CustomDictionary>(to dictionary: D.Type,
24+
dictionaryEntries: [D.Entry],
25+
requestOptions: RequestOptions? = nil,
26+
completion: @escaping ResultCallback<WaitableWrapper<DictionaryRevision>>) -> Operation where D.Entry: Encodable {
27+
let requests = dictionaryEntries.map(DictionaryRequest.add)
28+
let command = Command.Dictionaries.Batch(dictionary: D.self,
29+
requests: requests,
30+
clearExistingDictionaryEntries: false,
31+
requestOptions: requestOptions)
32+
return execute(command, completion: completion)
33+
}
34+
35+
/**
36+
Save dictionary entries
37+
38+
- Parameter dictionary: Target dictionary
39+
- Parameter dictionaryEntries: List of dictionary entries
40+
- Parameter requestOptions: Configure request locally with RequestOptions
41+
- Returns: Response object
42+
*/
43+
@discardableResult func saveDictionaryEntries<D: CustomDictionary>(to dictionary: D.Type,
44+
dictionaryEntries: [D.Entry],
45+
requestOptions: RequestOptions? = nil) throws -> WaitableWrapper<DictionaryRevision> where D.Entry: Encodable {
46+
let requests = dictionaryEntries.map(DictionaryRequest.add)
47+
let command = Command.Dictionaries.Batch(dictionary: D.self,
48+
requests: requests,
49+
clearExistingDictionaryEntries: false,
50+
requestOptions: requestOptions)
51+
return try execute(command)
52+
}
53+
54+
// MARK: - Replace dictionary entries
55+
56+
/**
57+
Replace dictionary entries
58+
59+
- Parameter dictionary: Target dictionary
60+
- Parameter dictionaryEntries: List of dictionary entries
61+
- Parameter requestOptions: Configure request locally with RequestOptions
62+
- Parameter completion: Result completion
63+
- Returns: Launched asynchronous operation
64+
*/
65+
@discardableResult func replaceDictionaryEntries<D: CustomDictionary>(in dictionary: D.Type,
66+
with dictionaryEntries: [D.Entry],
67+
requestOptions: RequestOptions? = nil,
68+
completion: @escaping ResultCallback<WaitableWrapper<DictionaryRevision>>) -> Operation where D.Entry: Encodable {
69+
let requests = dictionaryEntries.map(DictionaryRequest.add)
70+
let command = Command.Dictionaries.Batch(dictionary: D.self,
71+
requests: requests,
72+
clearExistingDictionaryEntries: true,
73+
requestOptions: requestOptions)
74+
return execute(command, completion: completion)
75+
}
76+
77+
/**
78+
Replace dictionary entries
79+
80+
- Parameter dictionary: Target dictionary
81+
- Parameter dictionaryEntries: List of dictionary entries
82+
- Parameter requestOptions: Configure request locally with RequestOptions
83+
- Returns: Response object
84+
*/
85+
@discardableResult func replaceDictionaryEntries<D: CustomDictionary>(in dictionary: D.Type,
86+
with dictionaryEntries: [D.Entry],
87+
requestOptions: RequestOptions? = nil) throws -> WaitableWrapper<DictionaryRevision> where D.Entry: Encodable {
88+
let requests = dictionaryEntries.map(DictionaryRequest.add)
89+
let command = Command.Dictionaries.Batch(dictionary: D.self,
90+
requests: requests,
91+
clearExistingDictionaryEntries: true,
92+
requestOptions: requestOptions)
93+
return try execute(command)
94+
}
95+
96+
// MARK: - Delete dictionary entries
97+
98+
/**
99+
Delete dictionary entries
100+
101+
- Parameter dictionary: Target dictionary
102+
- Parameter objectIDs: IDs of the objects to delete
103+
- Parameter requestOptions: Configure request locally with RequestOptions
104+
- Parameter completion: Result completion
105+
- Returns: Launched asynchronous operation
106+
*/
107+
108+
@discardableResult func deleteDictionaryEntries<D: CustomDictionary>(from dictionary: D.Type,
109+
withObjectIDs objectIDs: [ObjectID],
110+
requestOptions: RequestOptions? = nil,
111+
completion: @escaping ResultCallback<WaitableWrapper<DictionaryRevision>>) -> Operation where D.Entry: Encodable {
112+
let command = Command.Dictionaries.Batch(dictionary: D.self,
113+
requests: objectIDs.map(DictionaryRequest<D.Entry>.deleteEntry(withObjectID:)),
114+
clearExistingDictionaryEntries: false,
115+
requestOptions: requestOptions)
116+
return execute(command, completion: completion)
117+
}
118+
119+
/**
120+
Delete dictionary entries
121+
122+
- Parameter dictionary: Target dictionary
123+
- Parameter objectIDs: IDs of the objects to delete
124+
- Parameter requestOptions: Configure request locally with RequestOptions
125+
- Returns: Response object
126+
*/
127+
@discardableResult func deleteDictionaryEntries<D: CustomDictionary>(from dictionary: D.Type,
128+
withObjectIDs objectIDs: [ObjectID],
129+
requestOptions: RequestOptions? = nil) throws -> WaitableWrapper<DictionaryRevision> where D.Entry: Encodable {
130+
let command = Command.Dictionaries.Batch(dictionary: D.self,
131+
requests: objectIDs.map(DictionaryRequest<D.Entry>.deleteEntry(withObjectID:)),
132+
clearExistingDictionaryEntries: false,
133+
requestOptions: requestOptions)
134+
return try execute(command)
135+
}
136+
137+
// MARK: - Clear dictionary entries
138+
139+
/**
140+
Clear dictionary entries
141+
142+
- Parameter dictionary: Target dictionary
143+
- Parameter requestOptions: Configure request locally with RequestOptions
144+
- Parameter completion: Result completion
145+
- Returns: Launched asynchronous operation
146+
*/
147+
148+
@discardableResult func clearDictionaryEntries<D: CustomDictionary>(dictionary: D.Type,
149+
requestOptions: RequestOptions? = nil,
150+
completion: @escaping ResultCallback<WaitableWrapper<DictionaryRevision>>) -> Operation where D.Entry: Encodable {
151+
return replaceDictionaryEntries(in: D.self, with: [], requestOptions: requestOptions, completion: completion)
152+
}
153+
154+
/**
155+
Clear dictionary entries
156+
157+
- Parameter dictionary: Target dictionary
158+
- Parameter requestOptions: Configure request locally with RequestOptions
159+
- Returns: Response object
160+
*/
161+
@discardableResult func clearDictionaryEntries<D: CustomDictionary>(dictionary: D.Type,
162+
requestOptions: RequestOptions? = nil) throws -> WaitableWrapper<DictionaryRevision> where D.Entry: Encodable {
163+
return try replaceDictionaryEntries(in: D.self, with: [], requestOptions: requestOptions)
164+
}
165+
166+
// MARK: - Search dictionary entries
167+
168+
/**
169+
Search dictionary entries
170+
171+
- Parameter dictionary: Target dictionary
172+
- Parameter query: Search query
173+
- Parameter requestOptions: Configure request locally with RequestOptions
174+
- Parameter completion: Result completion
175+
- Returns: Launched asynchronous operation
176+
*/
177+
@discardableResult func searchDictionaryEntries<D: CustomDictionary>(in dictionary: D.Type,
178+
query: DictionaryQuery,
179+
requestOptions: RequestOptions? = nil,
180+
completion: @escaping ResultCallback<DictionarySearchResponse<D.Entry>>) -> Operation where D.Entry: Decodable {
181+
let command = Command.Dictionaries.Search(dictionaryName: D.name,
182+
query: query,
183+
requestOptions: requestOptions)
184+
return execute(command, completion: completion)
185+
}
186+
187+
/**
188+
Search dictionary entries
189+
190+
- Parameter dictionary: Target dictionary
191+
- Parameter query: Search query
192+
- Parameter requestOptions: Configure request locally with RequestOptions
193+
- Returns: Response object
194+
*/
195+
@discardableResult func searchDictionaryEntries<D: CustomDictionary>(in dictionary: D.Type,
196+
query: DictionaryQuery,
197+
requestOptions: RequestOptions? = nil) throws -> DictionarySearchResponse<D.Entry> where D.Entry: Decodable {
198+
let command = Command.Dictionaries.Search(dictionaryName: D.name,
199+
query: query,
200+
requestOptions: requestOptions)
201+
return try execute(command)
202+
}
203+
204+
// MARK: - Set dictionary settings
205+
206+
/**
207+
Set dictionary settings
208+
209+
- Parameter settings: Dictionaries settings
210+
- Parameter requestOptions: Configure request locally with RequestOptions
211+
- Parameter completion: Result completion
212+
- Returns: Launched asynchronous operation
213+
*/
214+
@discardableResult func setDictionarySettings(_ settings: DictionarySettings,
215+
requestOptions: RequestOptions? = nil,
216+
completion: @escaping ResultCallback<WaitableWrapper<AppRevision>>) -> Operation {
217+
let command = Command.Dictionaries.SetSettings(settings: settings,
218+
requestOptions: requestOptions)
219+
return execute(command, completion: completion)
220+
}
221+
222+
/**
223+
Set dictionary settings
224+
225+
- Parameter settings: Dictionaries settings
226+
- Parameter requestOptions: Configure request locally with RequestOptions
227+
- Returns: Response object
228+
*/
229+
@discardableResult func setDictionarySettings(_ settings: DictionarySettings,
230+
requestOptions: RequestOptions? = nil) throws -> WaitableWrapper<AppRevision> {
231+
let command = Command.Dictionaries.SetSettings(settings: settings,
232+
requestOptions: requestOptions)
233+
return try execute(command)
234+
}
235+
236+
// MARK: - Get dictionary settings
237+
238+
/**
239+
Get dictionary settings
240+
241+
- Parameter requestOptions: Configure request locally with RequestOptions
242+
- Parameter completion: Result completion
243+
- Returns: Launched asynchronous operation
244+
*/
245+
@discardableResult func getDictionarySettings(requestOptions: RequestOptions? = nil,
246+
completion: @escaping ResultCallback<DictionarySettings>) -> Operation {
247+
let command = Command.Dictionaries.GetSettings(requestOptions: requestOptions)
248+
return execute(command, completion: completion)
249+
}
250+
251+
/**
252+
Get dictionary settings
253+
254+
- Parameter requestOptions: Configure request locally with RequestOptions
255+
- Returns: Response object
256+
*/
257+
@discardableResult func getDictionarySettings(requestOptions: RequestOptions? = nil) throws -> DictionarySettings {
258+
let command = Command.Dictionaries.GetSettings(requestOptions: requestOptions)
259+
return try execute(command)
260+
}
261+
262+
}

0 commit comments

Comments
 (0)