|
17 | 17 |
|
18 | 18 | import { App } from '../app';
|
19 | 19 | import { deepCopy } from '../utils/deep-copy';
|
20 |
| -import { ErrorInfo, MessagingClientErrorCode, FirebaseMessagingError } from '../utils/error'; |
| 20 | +import { |
| 21 | + ErrorInfo, MessagingClientErrorCode, FirebaseMessagingError, FirebaseMessagingSessionError |
| 22 | +} from '../utils/error'; |
21 | 23 | import * as utils from '../utils';
|
22 | 24 | import * as validator from '../utils/validator';
|
23 | 25 | import { validateMessage } from './messaging-internal';
|
@@ -206,48 +208,71 @@ export class Messaging {
|
206 | 208 | MessagingClientErrorCode.INVALID_ARGUMENT, 'dryRun must be a boolean');
|
207 | 209 | }
|
208 | 210 |
|
209 |
| - const http2SessionHandler = this.useLegacyTransport ? undefined : new Http2SessionHandler(`https://${FCM_SEND_HOST}`) |
| 211 | + const http2SessionHandler = this.useLegacyTransport ? undefined : new Http2SessionHandler(`https://${FCM_SEND_HOST}`); |
210 | 212 |
|
211 | 213 | return this.getUrlPath()
|
212 | 214 | .then((urlPath) => {
|
213 |
| - const requests: Promise<SendResponse>[] = copy.map(async (message) => { |
214 |
| - validateMessage(message); |
215 |
| - const request: { message: Message; validate_only?: boolean } = { message }; |
216 |
| - if (dryRun) { |
217 |
| - request.validate_only = true; |
218 |
| - } |
219 |
| - |
220 |
| - if (http2SessionHandler){ |
221 |
| - return this.messagingRequestHandler.invokeHttp2RequestHandlerForSendResponse( |
222 |
| - FCM_SEND_HOST, urlPath, request, http2SessionHandler); |
223 |
| - } |
224 |
| - return this.messagingRequestHandler.invokeHttpRequestHandlerForSendResponse(FCM_SEND_HOST, urlPath, request); |
225 |
| - }); |
226 |
| - return Promise.allSettled(requests); |
227 |
| - }) |
228 |
| - .then((results) => { |
229 |
| - const responses: SendResponse[] = []; |
230 |
| - results.forEach(result => { |
231 |
| - if (result.status === 'fulfilled') { |
232 |
| - responses.push(result.value); |
233 |
| - } else { // rejected |
234 |
| - responses.push({ success: false, error: result.reason }) |
235 |
| - } |
236 |
| - }) |
237 |
| - const successCount: number = responses.filter((resp) => resp.success).length; |
238 |
| - return { |
239 |
| - responses, |
240 |
| - successCount, |
241 |
| - failureCount: responses.length - successCount, |
242 |
| - }; |
| 215 | + if (http2SessionHandler) { |
| 216 | + let sendResponsePromise: Promise<PromiseSettledResult<SendResponse>[]>; |
| 217 | + return new Promise((resolve: (result: PromiseSettledResult<SendResponse>[]) => void, reject) => { |
| 218 | + // Start session listeners |
| 219 | + http2SessionHandler.invoke().catch((error) => { |
| 220 | + const pendingBatchResponse = |
| 221 | + sendResponsePromise ? sendResponsePromise.then(this.parseSendResponses) : undefined; |
| 222 | + reject(new FirebaseMessagingSessionError(error, undefined, pendingBatchResponse)); |
| 223 | + }); |
| 224 | + |
| 225 | + // Start making requests |
| 226 | + const requests: Promise<SendResponse>[] = copy.map(async (message) => { |
| 227 | + validateMessage(message); |
| 228 | + const request: { message: Message; validate_only?: boolean; } = { message }; |
| 229 | + if (dryRun) { |
| 230 | + request.validate_only = true; |
| 231 | + } |
| 232 | + return this.messagingRequestHandler.invokeHttp2RequestHandlerForSendResponse( |
| 233 | + FCM_SEND_HOST, urlPath, request, http2SessionHandler); |
| 234 | + }); |
| 235 | + |
| 236 | + // Resolve once all requests have completed |
| 237 | + sendResponsePromise = Promise.allSettled(requests); |
| 238 | + sendResponsePromise.then(resolve); |
| 239 | + }); |
| 240 | + } else { |
| 241 | + const requests: Promise<SendResponse>[] = copy.map(async (message) => { |
| 242 | + validateMessage(message); |
| 243 | + const request: { message: Message; validate_only?: boolean; } = { message }; |
| 244 | + if (dryRun) { |
| 245 | + request.validate_only = true; |
| 246 | + } |
| 247 | + return this.messagingRequestHandler.invokeHttpRequestHandlerForSendResponse( |
| 248 | + FCM_SEND_HOST, urlPath, request); |
| 249 | + }); |
| 250 | + return Promise.allSettled(requests); |
| 251 | + } |
243 | 252 | })
|
| 253 | + .then(this.parseSendResponses) |
244 | 254 | .finally(() => {
|
245 |
| - if (http2SessionHandler){ |
246 |
| - http2SessionHandler.close() |
247 |
| - } |
| 255 | + http2SessionHandler?.close(); |
248 | 256 | });
|
249 | 257 | }
|
250 | 258 |
|
| 259 | + private parseSendResponses(results: PromiseSettledResult<SendResponse>[]): BatchResponse { |
| 260 | + const responses: SendResponse[] = []; |
| 261 | + results.forEach(result => { |
| 262 | + if (result.status === 'fulfilled') { |
| 263 | + responses.push(result.value); |
| 264 | + } else { // rejected |
| 265 | + responses.push({ success: false, error: result.reason }); |
| 266 | + } |
| 267 | + }); |
| 268 | + const successCount: number = responses.filter((resp) => resp.success).length; |
| 269 | + return { |
| 270 | + responses, |
| 271 | + successCount, |
| 272 | + failureCount: responses.length - successCount, |
| 273 | + }; |
| 274 | + } |
| 275 | + |
251 | 276 | /**
|
252 | 277 | * Sends the given multicast message to all the FCM registration tokens
|
253 | 278 | * specified in it.
|
|
0 commit comments