Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b53c94f
Preliminary impl of FCM batch support
hiranya911 Jan 29, 2019
6882354
Added BatchMessage class and tests
hiranya911 Jan 29, 2019
e75bcff
Refactored the FCM send operation
hiranya911 Jan 29, 2019
726ee09
Added unit tests for sendBatch() API
hiranya911 Jan 29, 2019
e3ad436
Refactored error handling
hiranya911 Jan 29, 2019
504e9ef
Refactored FCM logic into a new FirebaseMessagingClient class
hiranya911 Jan 30, 2019
80ed4b1
Using a separate request factory for child requests
hiranya911 Jan 30, 2019
057fcb5
Added the InstanceIdClient class for handling topic mgt ops
hiranya911 Jan 30, 2019
2c36d4c
Added license headers
hiranya911 Jan 30, 2019
c437042
Renamed BatchResponse as SendResponse
hiranya911 Jan 30, 2019
a3223fd
Added BatchResponse class; Renamed BatchMessage to MulticastMessage
hiranya911 Feb 6, 2019
5668421
Updated tests and docs
hiranya911 Feb 6, 2019
693711f
Updated documentation
hiranya911 Feb 6, 2019
46507d8
Added documentation and tests
hiranya911 Feb 6, 2019
b4d80e0
Merge branch 'master' into hkj-fcm-batch
hiranya911 Feb 6, 2019
0371159
Updated docs, changelog and annotations
hiranya911 Feb 6, 2019
5d57e07
Updated integration test to use multiple topics; Updated docs
hiranya911 Feb 7, 2019
f8f8c1e
Removing a redundant whitespace
hiranya911 Feb 11, 2019
7ecabe0
Reduced FCM batch size to 100 (#250)
hiranya911 Feb 19, 2019
3c0ae40
Setting the X-Client-Version header for FCM (#252)
hiranya911 Feb 22, 2019
c6367c0
Snippets for FCM sendAll() and sendMulticast() (#249)
hiranya911 Feb 25, 2019
1fbddcb
Addressing some documentation nits
hiranya911 Mar 12, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Renamed BatchResponse as SendResponse
  • Loading branch information
hiranya911 committed Jan 30, 2019
commit c43704229c24e9659e7fc33ab365c56f01c5fc0c
24 changes: 12 additions & 12 deletions src/main/java/com/google/firebase/messaging/FirebaseMessaging.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,55 +139,55 @@ protected String execute() throws FirebaseMessagingException {
* Sends all the messages in the given list as a single batch via Firebase Cloud Messaging.
*
* @param messages A non-null, non-empty list of messages
* @return A list of {@link BatchResponse} instances corresponding to the list of messages sent.
* @return A list of {@link SendResponse} instances corresponding to the list of messages sent.
*/
public List<BatchResponse> sendBatch(
public List<SendResponse> sendBatch(
@NonNull List<Message> messages) throws FirebaseMessagingException {
return sendBatch(messages, false);
}

public List<BatchResponse> sendBatch(
public List<SendResponse> sendBatch(
BatchMessage batch, boolean dryRun) throws FirebaseMessagingException {
checkNotNull(batch, "batch message must not be null");
return sendBatch(batch.getMessageList(), dryRun);
}

public List<BatchResponse> sendBatch(BatchMessage batch) throws FirebaseMessagingException {
public List<SendResponse> sendBatch(BatchMessage batch) throws FirebaseMessagingException {
return sendBatch(batch, false);
}

public List<BatchResponse> sendBatch(
public List<SendResponse> sendBatch(
List<Message> messages, boolean dryRun) throws FirebaseMessagingException {
return sendBatchOp(messages, dryRun).call();
}

public ApiFuture<List<BatchResponse>> sendBatchAsync(BatchMessage batch) {
public ApiFuture<List<SendResponse>> sendBatchAsync(BatchMessage batch) {
return sendBatchAsync(batch, false);
}

public ApiFuture<List<BatchResponse>> sendBatchAsync(BatchMessage batch, boolean dryRun) {
public ApiFuture<List<SendResponse>> sendBatchAsync(BatchMessage batch, boolean dryRun) {
checkNotNull(batch, "batch message must not be null");
return sendBatchAsync(batch.getMessageList(), dryRun);
}

public ApiFuture<List<BatchResponse>> sendBatchAsync(List<Message> messages) {
public ApiFuture<List<SendResponse>> sendBatchAsync(List<Message> messages) {
return sendBatchAsync(messages, false);
}

public ApiFuture<List<BatchResponse>> sendBatchAsync(List<Message> messages, boolean dryRun) {
public ApiFuture<List<SendResponse>> sendBatchAsync(List<Message> messages, boolean dryRun) {
return sendBatchOp(messages, dryRun).callAsync(app);
}

private CallableOperation<List<BatchResponse>, FirebaseMessagingException> sendBatchOp(
private CallableOperation<List<SendResponse>, FirebaseMessagingException> sendBatchOp(
final List<Message> messages, final boolean dryRun) {

final List<Message> immutableMessages = ImmutableList.copyOf(messages);
checkArgument(!immutableMessages.isEmpty(), "messages list must not be empty");
checkArgument(immutableMessages.size() <= 1000,
"messages list must not contain more than 1000 elements");
return new CallableOperation<List<BatchResponse>,FirebaseMessagingException>() {
return new CallableOperation<List<SendResponse>,FirebaseMessagingException>() {
@Override
protected List<BatchResponse> execute() throws FirebaseMessagingException {
protected List<SendResponse> execute() throws FirebaseMessagingException {
return messagingClient.sendBatch(messages, dryRun);
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ String send(Message message, boolean dryRun) throws FirebaseMessagingException {
}
}

List<BatchResponse> sendBatch(
List<SendResponse> sendBatch(
List<Message> messages, boolean dryRun) throws FirebaseMessagingException {
try {
return sendBatchRequest(messages, dryRun);
Expand All @@ -129,13 +129,13 @@ private String sendSingleRequest(Message message, boolean dryRun) throws IOExcep
try {
MessagingServiceResponse parsed = new MessagingServiceResponse();
jsonFactory.createJsonParser(response.getContent()).parseAndClose(parsed);
return parsed.getName();
return parsed.getMessageId();
} finally {
ApiClientUtils.disconnectQuietly(response);
}
}

private List<BatchResponse> sendBatchRequest(
private List<SendResponse> sendBatchRequest(
List<Message> messages, boolean dryRun) throws IOException {

MessagingBatchCallback callback = new MessagingBatchCallback();
Expand Down Expand Up @@ -223,21 +223,21 @@ private static FirebaseMessagingException newException(
private static class MessagingBatchCallback
implements BatchCallback<MessagingServiceResponse, MessagingServiceErrorResponse> {

private final ImmutableList.Builder<BatchResponse> responses = ImmutableList.builder();
private final ImmutableList.Builder<SendResponse> responses = ImmutableList.builder();

@Override
public void onSuccess(
MessagingServiceResponse response, HttpHeaders responseHeaders) {
responses.add(BatchResponse.fromResponse(response));
responses.add(SendResponse.fromMessageId(response.getMessageId()));
}

@Override
public void onFailure(
MessagingServiceErrorResponse error, HttpHeaders responseHeaders) {
responses.add(BatchResponse.fromException(newException(error)));
responses.add(SendResponse.fromException(newException(error)));
}

List<BatchResponse> getResponses() {
List<SendResponse> getResponses() {
return this.responses.build();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,13 @@

import com.google.common.base.Strings;
import com.google.common.primitives.Booleans;
import com.google.firebase.messaging.internal.MessagingServiceErrorResponse;
import com.google.firebase.messaging.internal.MessagingServiceResponse;

/**
* BatchResponse
*/
public final class BatchResponse {
public final class SendResponse {

private final String messageId;
private final FirebaseMessagingException exception;

public BatchResponse(String messageId, FirebaseMessagingException exception) {
private SendResponse(String messageId, FirebaseMessagingException exception) {
int argCount = Booleans.countTrue(!Strings.isNullOrEmpty(messageId), exception != null);
checkArgument(argCount == 1, "Exactly one of messageId or exception must be specified");
this.messageId = messageId;
Expand All @@ -50,11 +45,11 @@ public boolean isSuccessful() {
return !Strings.isNullOrEmpty(this.messageId);
}

static BatchResponse fromResponse(MessagingServiceResponse response) {
return new BatchResponse(response.getName(), null);
static SendResponse fromMessageId(String messageId) {
return new SendResponse(messageId, null);
}

static BatchResponse fromException(FirebaseMessagingException exception) {
return new BatchResponse(null, exception);
static SendResponse fromException(FirebaseMessagingException exception) {
return new SendResponse(null, exception);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
public class MessagingServiceResponse {

@Key("name")
private String name;
private String messageId;

public String getName() {
return this.name;
public String getMessageId() {
return this.messageId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,20 @@ public void testSendBatch() throws Exception {
.setToken("not-a-token")
.build());

List<BatchResponse> responses = FirebaseMessaging.getInstance().sendBatch(messages, true);
List<SendResponse> response = FirebaseMessaging.getInstance().sendBatch(messages, true);

assertEquals(3, responses.size());
assertTrue(responses.get(0).isSuccessful());
String id = responses.get(0).getMessageId();
assertEquals(3, response.size());
assertTrue(response.get(0).isSuccessful());
String id = response.get(0).getMessageId();
assertTrue(id != null && id.matches("^projects/.*/messages/.*$"));

assertTrue(responses.get(1).isSuccessful());
id = responses.get(1).getMessageId();
assertTrue(response.get(1).isSuccessful());
id = response.get(1).getMessageId();
assertTrue(id != null && id.matches("^projects/.*/messages/.*$"));

assertFalse(responses.get(2).isSuccessful());
assertNull(responses.get(2).getMessageId());
FirebaseMessagingException exception = responses.get(2).getException();
assertFalse(response.get(2).isSuccessful());
assertNull(response.get(2).getMessageId());
FirebaseMessagingException exception = response.get(2).getException();
assertNotNull(exception);
assertEquals("invalid-argument", exception.getErrorCode());
}
Expand All @@ -109,8 +109,8 @@ public void testLargeSendBatch() throws Exception {
for (int i = 0; i < 1000; i++) {
messages.add(Message.builder().setTopic("foo-bar").build());
}
List<BatchResponse> responses = FirebaseMessaging.getInstance().sendBatch(messages, true);
assertEquals(1000, responses.size());
List<SendResponse> response = FirebaseMessaging.getInstance().sendBatch(messages, true);
assertEquals(1000, response.size());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ public void testSendBatchSuccessWithList() throws Exception {
Message.builder().setTopic("topic2").build()
);

List<BatchResponse> responses = messaging.sendBatch(messages);
List<SendResponse> responses = messaging.sendBatch(messages);

assertSendBatchSuccess(responses, interceptor);
}
Expand All @@ -424,7 +424,7 @@ public void testSendBatchSuccessWithBatchMessage() throws Exception {
.addToken("token2")
.build();

List<BatchResponse> responses = messaging.sendBatch(batch);
List<SendResponse> responses = messaging.sendBatch(batch);

assertSendBatchSuccess(responses, interceptor);
}
Expand All @@ -439,7 +439,7 @@ public void testSendBatchAsyncSuccessWithList() throws Exception {
Message.builder().setTopic("topic2").build()
);

List<BatchResponse> responses = messaging.sendBatchAsync(messages).get();
List<SendResponse> responses = messaging.sendBatchAsync(messages).get();

assertSendBatchSuccess(responses, interceptor);
}
Expand All @@ -454,7 +454,7 @@ public void testSendBatchAsyncSuccessWithBatchMessage() throws Exception {
.addToken("token2")
.build();

List<BatchResponse> responses = messaging.sendBatchAsync(batch).get();
List<SendResponse> responses = messaging.sendBatchAsync(batch).get();

assertSendBatchSuccess(responses, interceptor);
}
Expand All @@ -470,7 +470,7 @@ public void testSendBatchFailureWithList() throws Exception {
Message.builder().setTopic("topic3").build()
);

List<BatchResponse> responses = messaging.sendBatch(messages);
List<SendResponse> responses = messaging.sendBatch(messages);

assertSendBatchFailure(responses, interceptor);
}
Expand All @@ -486,7 +486,7 @@ public void testSendBatchFailureWithBatchMessage() throws Exception {
.addToken("token3")
.build();

List<BatchResponse> responses = messaging.sendBatch(batch);
List<SendResponse> responses = messaging.sendBatch(batch);

assertSendBatchFailure(responses, interceptor);
}
Expand All @@ -502,7 +502,7 @@ public void testSendBatchAsyncFailureWithList() throws Exception {
Message.builder().setTopic("topic3").build()
);

List<BatchResponse> responses = messaging.sendBatchAsync(messages).get();
List<SendResponse> responses = messaging.sendBatchAsync(messages).get();

assertSendBatchFailure(responses, interceptor);
}
Expand All @@ -518,7 +518,7 @@ public void testSendBatchAsyncFailureWithBatchMessage() throws Exception {
.addToken("token3")
.build();

List<BatchResponse> responses = messaging.sendBatchAsync(batch).get();
List<SendResponse> responses = messaging.sendBatchAsync(batch).get();

assertSendBatchFailure(responses, interceptor);
}
Expand Down Expand Up @@ -958,34 +958,34 @@ private FirebaseMessaging getMessagingForBatchRequest(
}

private void assertSendBatchSuccess(
List<BatchResponse> responses, TestResponseInterceptor interceptor) throws IOException {
List<SendResponse> responses, TestResponseInterceptor interceptor) throws IOException {
assertEquals(2, responses.size());
for (int i = 0; i < 2; i++) {
BatchResponse response = responses.get(i);
assertTrue(response.isSuccessful());
assertEquals("projects/test-project/messages/" + (i + 1), response.getMessageId());
assertNull(response.getException());
SendResponse sendResponse = responses.get(i);
assertTrue(sendResponse.isSuccessful());
assertEquals("projects/test-project/messages/" + (i + 1), sendResponse.getMessageId());
assertNull(sendResponse.getException());
}
checkBatchRequestHeader(interceptor.getLastRequest());
checkBatchRequest(interceptor.getLastRequest(), 2);
}

private void assertSendBatchFailure(
List<BatchResponse> responses, TestResponseInterceptor interceptor) throws IOException {
List<SendResponse> responses, TestResponseInterceptor interceptor) throws IOException {
assertEquals(3, responses.size());
BatchResponse firstResponse = responses.get(0);
SendResponse firstResponse = responses.get(0);
assertTrue(firstResponse.isSuccessful());
assertEquals("projects/test-project/messages/1", firstResponse.getMessageId());
assertNull(firstResponse.getException());

BatchResponse secondResponse = responses.get(1);
SendResponse secondResponse = responses.get(1);
assertFalse(secondResponse.isSuccessful());
assertNull(secondResponse.getMessageId());
FirebaseMessagingException exception = secondResponse.getException();
assertNotNull(exception);
assertEquals("invalid-argument", exception.getErrorCode());

BatchResponse thirdResponse = responses.get(2);
SendResponse thirdResponse = responses.get(2);
assertFalse(thirdResponse.isSuccessful());
assertNull(thirdResponse.getMessageId());
exception = thirdResponse.getException();
Expand Down
58 changes: 58 additions & 0 deletions src/test/java/com/google/firebase/messaging/SendResponseTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2019 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.firebase.messaging;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class SendResponseTest {

@Test
public void testSuccessfulResponse() {
SendResponse response = SendResponse.fromMessageId("message-id");

assertEquals("message-id", response.getMessageId());
assertTrue(response.isSuccessful());
assertNull(response.getException());
}

@Test
public void testFailureResponse() {
FirebaseMessagingException exception = new FirebaseMessagingException("error-code",
"error-message", null);
SendResponse response = SendResponse.fromException(exception);

assertNull(response.getMessageId());
assertFalse(response.isSuccessful());
assertSame(exception, response.getException());
}

@Test(expected = IllegalArgumentException.class)
public void testMessageIdCannotBeNull() {
SendResponse.fromMessageId(null);
}

@Test(expected = IllegalArgumentException.class)
public void testMessageIdCannotBeEmpty() {
SendResponse.fromMessageId("");
}
}