@@ -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)
@@ -87,14 +88,138 @@ type BatchResponse struct {
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 -- i.e.
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 -- i.e.
113+ // 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 -- i.e.
125+ // 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 -- i.e.
146+ // none of the messages in the 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
96219// SendAll indicates a total failure -- i.e. none of the messages in the array could be sent.
97220// 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,11 +231,13 @@ 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
112237// SendAllDryRun indicates a total failure -- i.e. none of the messages in the array could be sent
113238// 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}
@@ -122,6 +249,8 @@ func (c *fcmClient) SendAllDryRun(ctx context.Context, messages []*Message) (*Ba
122249// responses list obtained from the return value corresponds to the order of the input tokens. An
123250// error from SendMulticast indicates a total failure -- i.e. the message could not be sent to any
124251// 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 {
@@ -142,6 +271,8 @@ func (c *fcmClient) SendMulticast(ctx context.Context, message *MulticastMessage
142271// the return value corresponds to the order of the input tokens. An error from SendMulticastDryRun
143272// indicates a total failure -- i.e. none of the messages were sent to FCM for validation. Partial
144273// 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