Skip to content

Commit cbbb54c

Browse files
committed
Add getResult Callback
1 parent 39df98b commit cbbb54c

File tree

6 files changed

+174
-25
lines changed

6 files changed

+174
-25
lines changed

Firestore/Source/API/FIRQuery.mm

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
#include "Firestore/core/src/util/exception.h"
6464
#include "Firestore/core/src/util/statusor.h"
6565
#include "Firestore/core/src/util/string_apple.h"
66+
#include "Firestore/core/swift/include/pipeline.h"
67+
#include "Firestore/core/swift/include/pipeline_result.h"
6668
#include "absl/strings/match.h"
6769

6870
namespace nanopb = firebase::firestore::nanopb;
@@ -71,6 +73,8 @@
7173
using firebase::firestore::google_firestore_v1_Value_fields;
7274
using firebase::firestore::api::Firestore;
7375
using firebase::firestore::api::MakeListenSource;
76+
using firebase::firestore::api::PipelineResult;
77+
using firebase::firestore::api::PipelineSnapshotListener;
7478
using firebase::firestore::api::Query;
7579
using firebase::firestore::api::QueryListenerRegistration;
7680
using firebase::firestore::api::QuerySnapshot;
@@ -175,6 +179,35 @@ - (void)getDocumentsWithCompletion:(void (^)(FIRQuerySnapshot *_Nullable snapsho
175179
_query.GetDocuments(Source::Default, [self wrapQuerySnapshotBlock:completion]);
176180
}
177181

182+
+ (PipelineSnapshotListener)
183+
wrapPipelineCallback:(std::shared_ptr<api::Firestore>)firestore
184+
completion:(void (^)(std::shared_ptr<std::vector<PipelineResult>> result,
185+
NSError *_Nullable error))completion {
186+
class Converter : public EventListener<std::vector<PipelineResult>> {
187+
public:
188+
explicit Converter(std::shared_ptr<api::Firestore> firestore, PipelineBlock completion)
189+
: firestore_(firestore), completion_(completion) {
190+
}
191+
192+
void OnEvent(StatusOr<std::vector<PipelineResult>> maybe_snapshot) override {
193+
if (maybe_snapshot.ok()) {
194+
completion_(
195+
std::make_shared<std::vector<PipelineResult>>(
196+
std::initializer_list<PipelineResult>{PipelineResult::GetTestResult(firestore_)}),
197+
nullptr);
198+
} else {
199+
completion_(nullptr, MakeNSError(maybe_snapshot.status()));
200+
}
201+
}
202+
203+
private:
204+
std::shared_ptr<api::Firestore> firestore_;
205+
PipelineBlock completion_;
206+
};
207+
208+
return absl::make_unique<Converter>(firestore, completion);
209+
}
210+
178211
- (void)getDocumentsWithSource:(FIRFirestoreSource)publicSource
179212
completion:(void (^)(FIRQuerySnapshot *_Nullable snapshot,
180213
NSError *_Nullable error))completion {
@@ -534,6 +567,29 @@ void OnEvent(StatusOr<QuerySnapshot> maybe_snapshot) override {
534567
return absl::make_unique<Converter>(block);
535568
}
536569

570+
+ (QuerySnapshotListener)wrapPipelineCallbackBlock:(FIRQuerySnapshotBlock)block {
571+
class Converter : public EventListener<QuerySnapshot> {
572+
public:
573+
explicit Converter(FIRQuerySnapshotBlock block) : block_(block) {
574+
}
575+
576+
void OnEvent(StatusOr<QuerySnapshot> maybe_snapshot) override {
577+
if (maybe_snapshot.ok()) {
578+
FIRQuerySnapshot *result =
579+
[[FIRQuerySnapshot alloc] initWithSnapshot:std::move(maybe_snapshot).ValueOrDie()];
580+
block_(result, nil);
581+
} else {
582+
block_(nil, MakeNSError(maybe_snapshot.status()));
583+
}
584+
}
585+
586+
private:
587+
FIRQuerySnapshotBlock block_;
588+
};
589+
590+
return absl::make_unique<Converter>(block);
591+
}
592+
537593
- (Filter)parseFieldFilter:(FSTUnaryFilter *)unaryFilter {
538594
auto describer = [&unaryFilter] {
539595
return MakeString(NSStringFromClass([unaryFilter.value class]));

Firestore/Source/Public/FirebaseFirestore/FIRQuery.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
#import <Foundation/Foundation.h>
18+
#import <memory>
1819

1920
#import "FIRFirestoreSource.h"
2021
#import "FIRListenerRegistration.h"
@@ -28,6 +29,24 @@
2829
@class FIRQuerySnapshot;
2930
@class FIRDocumentSnapshot;
3031

32+
namespace firebase {
33+
namespace firestore {
34+
namespace api {
35+
class Firestore;
36+
class PipelineResult;
37+
} // namespace api
38+
39+
namespace core {
40+
template <typename T>
41+
class EventListener;
42+
} // namespace core
43+
44+
} // namespace firestore
45+
} // namespace firebase
46+
47+
namespace api = firebase::firestore::api;
48+
namespace core = firebase::firestore::core;
49+
3150
NS_ASSUME_NONNULL_BEGIN
3251

3352
/**
@@ -37,6 +56,12 @@ typedef void (^FIRQuerySnapshotBlock)(FIRQuerySnapshot *_Nullable snapshot,
3756
NSError *_Nullable error)
3857
NS_SWIFT_UNAVAILABLE("Use Swift's closure syntax instead.");
3958

59+
typedef void (^PipelineBlock)(std::shared_ptr<std::vector<api::PipelineResult>> result,
60+
NSError *_Nullable error)
61+
NS_SWIFT_UNAVAILABLE("Use Swift's closure syntax instead.");
62+
63+
typedef std::shared_ptr<std::vector<api::PipelineResult>> PipelineResultVectorPtr;
64+
4065
/**
4166
* A `Query` refers to a query which you can read or listen to. You can also construct
4267
* refined `Query` objects by adding filters and ordering.
@@ -66,6 +91,11 @@ NS_SWIFT_NAME(Query)
6691
(void (^)(FIRQuerySnapshot *_Nullable snapshot, NSError *_Nullable error))completion
6792
NS_SWIFT_NAME(getDocuments(completion:));
6893

94+
+ (std::unique_ptr<core::EventListener<std::vector<api::PipelineResult>>>)
95+
wrapPipelineCallback:(std::shared_ptr<api::Firestore>)firestore
96+
completion:(void (^)(std::shared_ptr<std::vector<api::PipelineResult>> result,
97+
NSError *_Nullable error))completion
98+
NS_SWIFT_NAME(wrapPipelineCallback(firestore:completion:));
6999
/**
70100
* Reads the documents matching this query.
71101
*

Firestore/Swift/Source/SwiftAPI/Pipeline.swift

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,18 @@ public class Pipeline {
1414
}
1515

1616
@discardableResult
17-
public func GetPipelineResult() async throws -> PipelineResult {
18-
// return try await withCheckedThrowingContinuation { continuation in
19-
//
20-
// let callback: (
21-
// firebase.firestore.api.PipelineResult,
22-
// Bool
23-
// ) -> Void = { result, isSucceed in
24-
// if isSucceed {
25-
// continuation.resume(returning: PipelineResult(result))
26-
// } else {
27-
// continuation.resume(throwing: "ERROR!" as! Error)
28-
// }
29-
// }
30-
31-
// cppPtr.fetchDataWithCppCallback(callback)
32-
return PipelineResult(firebase.firestore.api.PipelineResult
33-
.GetTestResult(cppPtr.GetFirestore()))
17+
public func GetPipelineResult() async throws -> [PipelineResult] {
18+
return try await withCheckedThrowingContinuation { continuation in
19+
let listener = Query.wrapPipelineCallback(firestore: cppPtr.GetFirestore()) {
20+
result, error in
21+
if let error {
22+
continuation.resume(throwing: error)
23+
} else {
24+
// Our callbacks guarantee that we either return an error or a progress event.
25+
continuation.resume(returning: PipelineResult.convertToArrayFromCppVector(result))
26+
}
27+
}
28+
cppPtr.GetPipelineResult(listener)
29+
}
3430
}
3531
}

Firestore/Swift/Source/SwiftAPI/PipelineResult.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,24 @@
55
// Created by Cheryl Lin on 2024-12-18.
66
//
77

8+
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
89
public class PipelineResult {
910
let cppPtr: firebase.firestore.api.PipelineResult
1011

1112
public init(_ cppSource: firebase.firestore.api.PipelineResult) {
1213
cppPtr = cppSource
1314
}
15+
16+
static func convertToArrayFromCppVector(_ vectorPtr: PipelineResultVectorPtr)
17+
-> [PipelineResult] {
18+
// Create a Swift array and populate it by iterating over the C++ vector
19+
var swiftArray: [PipelineResult] = []
20+
21+
for index in vectorPtr.pointee.indices {
22+
let cppResult = vectorPtr.pointee[index]
23+
swiftArray.append(PipelineResult(cppResult))
24+
}
25+
26+
return swiftArray
27+
}
1428
}

Firestore/core/swift/include/pipeline.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ class Pipeline {
3131
public:
3232
Pipeline(std::shared_ptr<Firestore> firestore, Stage stage);
3333

34-
void GetPipelineResult(
35-
std::function<void(PipelineResult, bool)> callback) const;
34+
void GetPipelineResult(PipelineSnapshotListener callback) const;
3635

3736
std::shared_ptr<Firestore> GetFirestore() const {
3837
return firestore_;

Firestore/core/swift/src/pipeline.cc

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,78 @@
11
#include "Firestore/core/swift/include/pipeline.h"
2+
3+
#include <future> // NOLINT(build/c++11)
4+
#include <memory>
5+
26
#include "Firestore/core/include/firebase/firestore/timestamp.h"
37
#include "Firestore/core/src/api/firestore.h"
8+
#include "Firestore/core/src/api/listener_registration.h"
9+
#include "Firestore/core/src/api/source.h"
410
#include "Firestore/core/src/core/event_listener.h"
11+
#include "Firestore/core/src/core/listen_options.h"
12+
#include "Firestore/core/src/core/view_snapshot.h"
513
#include "Firestore/core/swift/include/pipeline_result.h"
614

715
namespace firebase {
816
namespace firestore {
917

1018
namespace api {
1119

20+
using core::EventListener;
21+
using core::ListenOptions;
22+
using core::ViewSnapshot;
23+
1224
Pipeline::Pipeline(std::shared_ptr<Firestore> firestore, Stage stage)
1325
: firestore_(firestore), stage_(stage) {
1426
}
1527

16-
void Pipeline::GetPipelineResult(
17-
std::function<void(PipelineResult, bool)> callback) const {
18-
callback(PipelineResult(firestore_, std::make_shared<Timestamp>(0, 0),
19-
std::make_shared<Timestamp>(0, 0),
20-
std::make_shared<Timestamp>(0, 0)),
21-
true);
28+
void Pipeline::GetPipelineResult(PipelineSnapshotListener callback) const {
29+
ListenOptions options(
30+
/*include_query_metadata_changes=*/true,
31+
/*include_document_metadata_changes=*/true,
32+
/*wait_for_sync_when_online=*/true);
33+
34+
class ListenOnce : public EventListener<std::vector<PipelineResult>> {
35+
public:
36+
ListenOnce(PipelineSnapshotListener listener)
37+
: listener_(std::move(listener)) {
38+
}
39+
40+
void OnEvent(
41+
StatusOr<std::vector<PipelineResult>> maybe_snapshot) override {
42+
if (!maybe_snapshot.ok()) {
43+
listener_->OnEvent(std::move(maybe_snapshot));
44+
return;
45+
}
46+
47+
std::vector<PipelineResult> snapshot =
48+
std::move(maybe_snapshot).ValueOrDie();
49+
50+
// Remove query first before passing event to user to avoid user actions
51+
// affecting the now stale query.
52+
std::unique_ptr<ListenerRegistration> registration =
53+
registration_promise_.get_future().get();
54+
registration->Remove();
55+
56+
listener_->OnEvent(std::move(snapshot));
57+
};
58+
59+
void Resolve(std::unique_ptr<ListenerRegistration> registration) {
60+
registration_promise_.set_value(std::move(registration));
61+
}
62+
63+
private:
64+
PipelineSnapshotListener listener_;
65+
66+
std::promise<std::unique_ptr<ListenerRegistration>> registration_promise_;
67+
};
68+
69+
auto listener = absl::make_unique<ListenOnce>(std::move(callback));
70+
auto* listener_unowned = listener.get();
71+
72+
// std::unique_ptr<ListenerRegistration> registration =
73+
// AddSnapshotListener(std::move(options), std::move(listener));
74+
//
75+
// listener_unowned->Resolve(std::move(registration));
2276
}
2377

2478
} // namespace api

0 commit comments

Comments
 (0)