Skip to content

Commit 74c6052

Browse files
committed
demo possible API surface for CF3 Streaming
1 parent cf5fe2e commit 74c6052

File tree

5 files changed

+164
-0
lines changed

5 files changed

+164
-0
lines changed

firebase-functions/api.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ package com.google.firebase.functions {
8686
method @NonNull public com.google.android.gms.tasks.Task<com.google.firebase.functions.HttpsCallableResult> call();
8787
method public long getTimeout();
8888
method public void setTimeout(long timeout, @NonNull java.util.concurrent.TimeUnit units);
89+
method @NonNull public com.google.firebase.functions.StreamFunctionsTask stream(@Nullable Object data = null);
90+
method @NonNull public kotlinx.coroutines.flow.Flow<com.google.firebase.functions.HttpsCallableResult> streamFlow(@Nullable Object data = null);
8991
method @NonNull public com.google.firebase.functions.HttpsCallableReference withTimeout(long timeout, @NonNull java.util.concurrent.TimeUnit units);
9092
property public final long timeout;
9193
}
@@ -95,6 +97,28 @@ package com.google.firebase.functions {
9597
field @Nullable public final Object data;
9698
}
9799

100+
public final class StreamFunctionsTask extends com.google.android.gms.tasks.Task<com.google.firebase.functions.HttpsCallableResult> {
101+
ctor public StreamFunctionsTask();
102+
method @NonNull public com.google.android.gms.tasks.Task<com.google.firebase.functions.HttpsCallableResult> addOnFailureListener(@NonNull com.google.android.gms.tasks.OnFailureListener p0);
103+
method @NonNull public com.google.android.gms.tasks.Task<com.google.firebase.functions.HttpsCallableResult> addOnFailureListener(@NonNull android.app.Activity p0, @NonNull com.google.android.gms.tasks.OnFailureListener p1);
104+
method @NonNull public com.google.android.gms.tasks.Task<com.google.firebase.functions.HttpsCallableResult> addOnFailureListener(@NonNull java.util.concurrent.Executor p0, @NonNull com.google.android.gms.tasks.OnFailureListener p1);
105+
method @NonNull public com.google.firebase.functions.StreamFunctionsTask addOnStreamListener(@NonNull com.google.firebase.functions.StreamListener listener);
106+
method @NonNull public com.google.android.gms.tasks.Task<com.google.firebase.functions.HttpsCallableResult> addOnSuccessListener(@NonNull java.util.concurrent.Executor p0, @NonNull com.google.android.gms.tasks.OnSuccessListener<? super com.google.firebase.functions.HttpsCallableResult> p1);
107+
method @NonNull public com.google.android.gms.tasks.Task<com.google.firebase.functions.HttpsCallableResult> addOnSuccessListener(@NonNull android.app.Activity p0, @NonNull com.google.android.gms.tasks.OnSuccessListener<? super com.google.firebase.functions.HttpsCallableResult> p1);
108+
method @NonNull public com.google.android.gms.tasks.Task<com.google.firebase.functions.HttpsCallableResult> addOnSuccessListener(@NonNull com.google.android.gms.tasks.OnSuccessListener<? super com.google.firebase.functions.HttpsCallableResult> p0);
109+
method @Nullable public Exception getException();
110+
method @NonNull public com.google.firebase.functions.HttpsCallableResult getResult();
111+
method @NonNull public <X extends java.lang.Throwable> com.google.firebase.functions.HttpsCallableResult getResult(@NonNull Class<X> p0);
112+
method public boolean isCanceled();
113+
method public boolean isComplete();
114+
method public boolean isSuccessful();
115+
method public void removeOnStreamListener(@NonNull com.google.firebase.functions.StreamListener listener);
116+
}
117+
118+
public fun interface StreamListener {
119+
method public void onNext(@NonNull Object message);
120+
}
121+
98122
}
99123

100124
package com.google.firebase.functions.ktx {

firebase-functions/src/main/java/com/google/firebase/functions/HttpsCallableReference.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ package com.google.firebase.functions
1515

1616
import androidx.annotation.VisibleForTesting
1717
import com.google.android.gms.tasks.Task
18+
import kotlinx.coroutines.flow.Flow
1819
import java.net.URL
1920
import java.util.concurrent.TimeUnit
2021

@@ -125,6 +126,16 @@ public class HttpsCallableReference {
125126
}
126127
}
127128

129+
// if you prefer to use Tasks (eg. from Java)
130+
public fun stream(data: Any? = null): StreamFunctionsTask {
131+
TODO("Not yet implemented")
132+
}
133+
134+
// if you use Kotlin Coroutines (not supported in Java)
135+
public fun streamFlow(data: Any? = null): Flow<HttpsCallableResult> {
136+
TODO("Not yet implemented")
137+
}
138+
128139
/**
129140
* Changes the timeout for calls from this instance of Functions. The default is 60 seconds.
130141
*
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.google.firebase.functions
2+
3+
import android.app.Activity
4+
import com.google.android.gms.tasks.OnFailureListener
5+
import com.google.android.gms.tasks.OnSuccessListener
6+
import com.google.android.gms.tasks.Task
7+
import java.util.Queue
8+
import java.util.concurrent.ConcurrentLinkedQueue
9+
import java.util.concurrent.Executor
10+
11+
public class StreamFunctionsTask : Task<HttpsCallableResult>() {
12+
13+
private val listenerQueue: Queue<StreamListener> = ConcurrentLinkedQueue()
14+
15+
public fun addOnStreamListener(listener: StreamListener): StreamFunctionsTask {
16+
listenerQueue.add(listener)
17+
// TODO: Attach the listener
18+
return this
19+
}
20+
21+
public fun removeOnStreamListener(listener: StreamListener) {
22+
listenerQueue.remove(listener)
23+
// TODO: Remove the listener
24+
}
25+
26+
// ALL OVERRIDES LISTED BELOW ARE FROM THE Task INTERFACE
27+
override fun getException(): Exception? {
28+
listenerQueue.clear()
29+
TODO("Not yet implemented")
30+
}
31+
32+
override fun getResult(): HttpsCallableResult {
33+
listenerQueue.clear()
34+
TODO("Not yet implemented")
35+
}
36+
37+
override fun addOnFailureListener(p0: OnFailureListener): Task<HttpsCallableResult> {
38+
TODO("Not yet implemented")
39+
}
40+
41+
override fun addOnFailureListener(
42+
p0: Activity,
43+
p1: OnFailureListener
44+
): Task<HttpsCallableResult> {
45+
TODO("Not yet implemented")
46+
}
47+
48+
override fun addOnFailureListener(
49+
p0: Executor,
50+
p1: OnFailureListener
51+
): Task<HttpsCallableResult> {
52+
TODO("Not yet implemented")
53+
}
54+
55+
override fun addOnSuccessListener(
56+
p0: Executor,
57+
p1: OnSuccessListener<in HttpsCallableResult>
58+
): Task<HttpsCallableResult> {
59+
TODO("Not yet implemented")
60+
}
61+
62+
override fun addOnSuccessListener(
63+
p0: Activity,
64+
p1: OnSuccessListener<in HttpsCallableResult>
65+
): Task<HttpsCallableResult> {
66+
TODO("Not yet implemented")
67+
}
68+
69+
override fun addOnSuccessListener(p0: OnSuccessListener<in HttpsCallableResult>): Task<HttpsCallableResult> {
70+
TODO("Not yet implemented")
71+
}
72+
73+
74+
override fun <X : Throwable?> getResult(p0: Class<X>): HttpsCallableResult {
75+
TODO("Not yet implemented")
76+
}
77+
78+
override fun isCanceled(): Boolean {
79+
TODO("Not yet implemented")
80+
}
81+
82+
override fun isComplete(): Boolean {
83+
TODO("Not yet implemented")
84+
}
85+
86+
override fun isSuccessful(): Boolean {
87+
TODO("Not yet implemented")
88+
}
89+
90+
91+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.google.firebase.functions
2+
3+
public fun interface StreamListener {
4+
/** Called when a new event is received. */
5+
public fun onNext(message: Any)
6+
}

firebase-functions/src/test/java/com/google/firebase/functions/FunctionsTests.kt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.google.firebase.FirebaseOptions
2424
import com.google.firebase.app
2525
import com.google.firebase.initialize
2626
import com.google.firebase.platforminfo.UserAgentPublisher
27+
import kotlinx.coroutines.flow.catch
2728
import java.net.URL
2829
import org.junit.After
2930
import org.junit.Before
@@ -147,4 +148,35 @@ class AppCheckLimitedUseTest : BaseTestCase() {
147148
}
148149
assertThat(callable.usesLimitedUseFacTokens()).isFalse()
149150
}
151+
152+
@Test
153+
fun `Demo stream usage from Java`() {
154+
val input = mapOf("data" to "Hello, World!")
155+
156+
Firebase.functions.getHttpsCallable("genStream").stream(input)
157+
.addOnStreamListener { chunk ->
158+
println("Received: $chunk")
159+
}
160+
.addOnFailureListener { error ->
161+
println("Error: $error")
162+
}
163+
.addOnSuccessListener { result ->
164+
println("Stream complete: ${result.data}")
165+
}
166+
}
167+
168+
@Test
169+
suspend fun `Demo stream usage from Kotlin`() {
170+
val input = mapOf("data" to "Hello, World!")
171+
172+
Firebase.functions.getHttpsCallable("genStream").streamFlow(input)
173+
.catch {
174+
println("Error: $it")
175+
}
176+
.collect { chunk ->
177+
println("Received: $chunk")
178+
}
179+
180+
// This is consistent with the Vertex AI in Firebase SDK
181+
}
150182
}

0 commit comments

Comments
 (0)