Skip to content

Commit

Permalink
Add async overload for search API
Browse files Browse the repository at this point in the history
This acts as an example for the conversation being held in issue meilisearch#332.

Async/await continues to grow in popularity and all modern codebases are moving towards its usage. This commit demonstrates how we can add support for Swift Concurrency without breaking existing compatibility with older operating systems.

For a test I have taken an existing test, copied it, and converted it for async/await. In this instance, removing the XCTestExpectation and simply using an async test available since Xcode 13 back in September 2021.
  • Loading branch information
Sherlouk committed Sep 28, 2023
1 parent 33d66ff commit e611698
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
22 changes: 21 additions & 1 deletion Sources/MeiliSearch/Indexes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public struct Indexes {
private let documents: Documents

// Search methods
private let search: Search
fileprivate let search: Search

// Settings methods
private let settings: Settings
Expand Down Expand Up @@ -1101,3 +1101,23 @@ public struct Indexes {
}
}
}

// MARK: Swift Concurrency (Async/Await)

@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
extension Indexes {
/**
Search in the index.

- Parameter searchParameters: Options on search.
- Throws: Error if a failure occurred.
- Returns: On completion if the request was successful a `Searchable<T>` instance is returned containing the values.
*/
public func search<T: Codable & Equatable>(_ searchParameters: SearchParameters) async throws -> Searchable<T> {
try await withCheckedThrowingContinuation { continuation in
self.search.search(self.uid, searchParameters) { result in
continuation.resume(with: result)
}
}
}
}
40 changes: 40 additions & 0 deletions Tests/MeiliSearchUnitTests/SearchTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,46 @@ class SearchTests: XCTestCase {

self.wait(for: [expectation], timeout: TESTS_TIME_OUT)
}

@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
func testSearchForBotmanMovieAsync() async throws {
let jsonString = """
{
"hits": [
{
"id": 29751,
"title": "Batman Unmasked: The Psychology of the Dark Knight",
"poster": "https://image.tmdb.org/t/p/w1280/jjHu128XLARc2k4cJrblAvZe0HE.jpg",
"overview": "Delve into the world of Batman and the vigilante justice tha",
"release_date": "2020-04-04T19:59:49.259572Z"
},
{
"id": 471474,
"title": "Batman: Gotham by Gaslight",
"poster": "https://image.tmdb.org/t/p/w1280/7souLi5zqQCnpZVghaXv0Wowi0y.jpg",
"overview": "ve Victorian Age Gotham City, Batman begins his war on crime",
"release_date": "2020-04-04T19:59:49.259572Z"
}
],
"offset": 0,
"limit": 20,
"processingTimeMs": 2,
"estimatedTotalHits": 2,
"query": "botman"
}
"""

// Prepare the mock server
let data = jsonString.data(using: .utf8)!
let stubSearchResult: Searchable<Movie> = try! Constants.customJSONDecoder.decode(Searchable<Movie>.self, from: data)
session.pushData(jsonString)

// Start the test with the mocked server
let searchParameters = SearchParameters.query("botman")

let searchResult: Searchable<Movie> = try await self.index.search(searchParameters)
XCTAssertEqual(stubSearchResult, searchResult)
}

func testSearchForBotmanMovieFacets() {
let jsonString = """
Expand Down

0 comments on commit e611698

Please sign in to comment.