@@ -27,6 +27,7 @@ import (
2727 "mime/multipart"
2828 "net/http"
2929 "net/textproto"
30+ "sync"
3031
3132 "firebase.google.com/go/v4/internal"
3233)
@@ -80,21 +81,145 @@ type SendResponse struct {
8081 Error error
8182}
8283
83- // BatchResponse represents the response from the ` SendAll()` and ` SendMulticast()` APIs.
84+ // BatchResponse represents the response from the SendAll() and SendMulticast() APIs.
8485type BatchResponse struct {
8586 SuccessCount int
8687 FailureCount int
8788 Responses []* SendResponse
8889}
8990
91+ // SendEach sends the messages in the given array via Firebase Cloud Messaging.
92+ //
93+ // The messages array may contain up to 500 messages. Unlike SendAll(), SendEach sends the entire
94+ // array of messages by making a single HTTP call for each message. The responses list
95+ // obtained from the return value corresponds to the order of the input messages. An error
96+ // from SendEach or a BatchResponse with all failures indicates a total failure, meaning that
97+ // none of the messages in the list could be sent. Partial failures or no failures are only
98+ // indicated by a BatchResponse return value.
99+ func (c * fcmClient ) SendEach (ctx context.Context , messages []* Message ) (* BatchResponse , error ) {
100+ return c .sendEachInBatch (ctx , messages , false )
101+ }
102+
103+ // SendEachDryRun sends the messages in the given array via Firebase Cloud Messaging in the
104+ // dry run (validation only) mode.
105+ //
106+ // This function does not actually deliver any messages to target devices. Instead, it performs all
107+ // the SDK-level and backend validations on the messages, and emulates the send operation.
108+ //
109+ // The messages array may contain up to 500 messages. Unlike SendAllDryRun(), SendEachDryRun sends
110+ // the entire array of messages by making a single HTTP call for each message. The responses list
111+ // obtained from the return value corresponds to the order of the input messages. An error
112+ // from SendEachDryRun or a BatchResponse with all failures indicates a total failure, meaning
113+ // that none of the messages in the list could be sent. Partial failures or no failures are only
114+ // indicated by a BatchResponse return value.
115+ func (c * fcmClient ) SendEachDryRun (ctx context.Context , messages []* Message ) (* BatchResponse , error ) {
116+ return c .sendEachInBatch (ctx , messages , true )
117+ }
118+
119+ // SendMulticast sends the given multicast message to all the FCM registration tokens specified.
120+ //
121+ // The tokens array in MulticastMessage may contain up to 500 tokens. SendMulticast uses the
122+ // SendEach() function to send the given message to all the target recipients. The
123+ // responses list obtained from the return value corresponds to the order of the input tokens. An error
124+ // from SendEachForMulticast or a BatchResponse with all failures indicates a total failure, meaning
125+ // that none of the messages in the list could be sent. Partial failures or no failures are only
126+ // indicated by a BatchResponse return value.
127+ func (c * fcmClient ) SendEachForMulticast (ctx context.Context , message * MulticastMessage ) (* BatchResponse , error ) {
128+ messages , err := toMessages (message )
129+ if err != nil {
130+ return nil , err
131+ }
132+
133+ return c .SendEach (ctx , messages )
134+ }
135+
136+ // SendEachForMulticastDryRun sends the given multicast message to all the specified FCM registration
137+ // tokens in the dry run (validation only) mode.
138+ //
139+ // This function does not actually deliver any messages to target devices. Instead, it performs all
140+ // the SDK-level and backend validations on the messages, and emulates the send operation.
141+ //
142+ // The tokens array in MulticastMessage may contain up to 500 tokens. SendEachForMulticastDryRunn uses the
143+ // SendEachDryRun() function to send the given message. The responses list obtained from
144+ // the return value corresponds to the order of the input tokens. An error from SendEachForMulticastDryRun
145+ // or a BatchResponse with all failures indicates a total failure, meaning that of the messages in the
146+ // list could be sent. Partial failures or no failures are only
147+ // indicated by a BatchResponse return value.
148+ func (c * fcmClient ) SendEachForMulticastDryRun (ctx context.Context , message * MulticastMessage ) (* BatchResponse , error ) {
149+ messages , err := toMessages (message )
150+ if err != nil {
151+ return nil , err
152+ }
153+
154+ return c .SendEachDryRun (ctx , messages )
155+ }
156+
157+ func (c * fcmClient ) sendEachInBatch (ctx context.Context , messages []* Message , dryRun bool ) (* BatchResponse , error ) {
158+ if len (messages ) == 0 {
159+ return nil , errors .New ("messages must not be nil or empty" )
160+ }
161+
162+ if len (messages ) > maxMessages {
163+ return nil , fmt .Errorf ("messages must not contain more than %d elements" , maxMessages )
164+ }
165+
166+ var responses []* SendResponse = make ([]* SendResponse , len (messages ))
167+ var wg sync.WaitGroup
168+
169+ for idx , m := range messages {
170+ if err := validateMessage (m ); err != nil {
171+ return nil , fmt .Errorf ("invalid message at index %d: %v" , idx , err )
172+ }
173+ wg .Add (1 )
174+ go func (idx int , m * Message , dryRun bool , responses []* SendResponse ) {
175+ defer wg .Done ()
176+ var resp string
177+ var err error
178+ if dryRun {
179+ resp , err = c .SendDryRun (ctx , m )
180+ } else {
181+ resp , err = c .Send (ctx , m )
182+ }
183+ if err == nil {
184+ responses [idx ] = & SendResponse {
185+ Success : true ,
186+ MessageID : resp ,
187+ }
188+ } else {
189+ responses [idx ] = & SendResponse {
190+ Success : false ,
191+ Error : err ,
192+ }
193+ }
194+ }(idx , m , dryRun , responses )
195+ }
196+ // Wait for all SendDryRun/Send calls to finish
197+ wg .Wait ()
198+
199+ successCount := 0
200+ for _ , r := range responses {
201+ if r .Success {
202+ successCount ++
203+ }
204+ }
205+
206+ return & BatchResponse {
207+ Responses : responses ,
208+ SuccessCount : successCount ,
209+ FailureCount : len (responses ) - successCount ,
210+ }, nil
211+ }
212+
90213// SendAll sends the messages in the given array via Firebase Cloud Messaging.
91214//
92215// The messages array may contain up to 500 messages. SendAll employs batching to send the entire
93- // array of mssages as a single RPC call. Compared to the ` Send()` function,
216+ // array of messages as a single RPC call. Compared to the Send() function,
94217// this is a significantly more efficient way to send multiple messages. The responses list
95218// obtained from the return value corresponds to the order of the input messages. An error from
96- // SendAll indicates a total failure -- i.e. none of the messages in the array could be sent.
97- // Partial failures are indicated by a `BatchResponse` return value.
219+ // SendAll indicates a total failure, meaning that none of the messages in the array could be
220+ // sent. Partial failures are indicated by a BatchResponse return value.
221+ //
222+ // Deprecated: Use SendEach instead.
98223func (c * fcmClient ) SendAll (ctx context.Context , messages []* Message ) (* BatchResponse , error ) {
99224 return c .sendBatch (ctx , messages , false )
100225}
@@ -106,22 +231,26 @@ func (c *fcmClient) SendAll(ctx context.Context, messages []*Message) (*BatchRes
106231// the SDK-level and backend validations on the messages, and emulates the send operation.
107232//
108233// The messages array may contain up to 500 messages. SendAllDryRun employs batching to send the
109- // entire array of mssages as a single RPC call. Compared to the ` SendDryRun()` function, this
234+ // entire array of messages as a single RPC call. Compared to the SendDryRun() function, this
110235// is a significantly more efficient way to validate sending multiple messages. The responses list
111236// obtained from the return value corresponds to the order of the input messages. An error from
112- // SendAllDryRun indicates a total failure -- i.e. none of the messages in the array could be sent
113- // for validation. Partial failures are indicated by a `BatchResponse` return value.
237+ // SendAllDryRun indicates a total failure, meaning that none of the messages in the array could
238+ // be sent for validation. Partial failures are indicated by a BatchResponse return value.
239+ //
240+ // Deprecated: Use SendEachDryRun instead.
114241func (c * fcmClient ) SendAllDryRun (ctx context.Context , messages []* Message ) (* BatchResponse , error ) {
115242 return c .sendBatch (ctx , messages , true )
116243}
117244
118245// SendMulticast sends the given multicast message to all the FCM registration tokens specified.
119246//
120247// The tokens array in MulticastMessage may contain up to 500 tokens. SendMulticast uses the
121- // ` SendAll()` function to send the given message to all the target recipients. The
248+ // SendAll() function to send the given message to all the target recipients. The
122249// responses list obtained from the return value corresponds to the order of the input tokens. An
123- // error from SendMulticast indicates a total failure -- i.e. the message could not be sent to any
124- // of the recipients. Partial failures are indicated by a `BatchResponse` return value.
250+ // error from SendMulticast indicates a total failure, meaning that the message could not be sent
251+ // to any of the recipients. Partial failures are indicated by a BatchResponse return value.
252+ //
253+ // Deprecated: Use SendEachForMulticast instead.
125254func (c * fcmClient ) SendMulticast (ctx context.Context , message * MulticastMessage ) (* BatchResponse , error ) {
126255 messages , err := toMessages (message )
127256 if err != nil {
@@ -138,10 +267,12 @@ func (c *fcmClient) SendMulticast(ctx context.Context, message *MulticastMessage
138267// the SDK-level and backend validations on the messages, and emulates the send operation.
139268//
140269// The tokens array in MulticastMessage may contain up to 500 tokens. SendMulticastDryRun uses the
141- // ` SendAllDryRun()` function to send the given message. The responses list obtained from
270+ // SendAllDryRun() function to send the given message. The responses list obtained from
142271// the return value corresponds to the order of the input tokens. An error from SendMulticastDryRun
143- // indicates a total failure -- i.e. none of the messages were sent to FCM for validation. Partial
144- // failures are indicated by a `BatchResponse` return value.
272+ // indicates a total failure, meaning that none of the messages were sent to FCM for validation.
273+ // Partial failures are indicated by a BatchResponse return value.
274+ //
275+ // Deprecated: Use SendEachForMulticastDryRun instead.
145276func (c * fcmClient ) SendMulticastDryRun (ctx context.Context , message * MulticastMessage ) (* BatchResponse , error ) {
146277 messages , err := toMessages (message )
147278 if err != nil {
0 commit comments