Skip to content

Commit d515faf

Browse files
Merge dev into master
2 parents db240e4 + 9b23ddc commit d515faf

14 files changed

+3032
-111
lines changed

firebase.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"firebase.google.com/go/v4/iid"
3232
"firebase.google.com/go/v4/internal"
3333
"firebase.google.com/go/v4/messaging"
34+
"firebase.google.com/go/v4/remoteconfig"
3435
"firebase.google.com/go/v4/storage"
3536
"google.golang.org/api/option"
3637
"google.golang.org/api/transport"
@@ -39,7 +40,7 @@ import (
3940
var defaultAuthOverrides = make(map[string]interface{})
4041

4142
// Version of the Firebase Go Admin SDK.
42-
const Version = "4.16.1"
43+
const Version = "4.17.0"
4344

4445
// firebaseEnvName is the name of the environment variable with the Config.
4546
const firebaseEnvName = "FIREBASE_CONFIG"
@@ -138,6 +139,16 @@ func (a *App) AppCheck(ctx context.Context) (*appcheck.Client, error) {
138139
return appcheck.NewClient(ctx, conf)
139140
}
140141

142+
// RemoteConfig returns an instance of remoteconfig.Client.
143+
func (a *App) RemoteConfig(ctx context.Context) (*remoteconfig.Client, error) {
144+
conf := &internal.RemoteConfigClientConfig{
145+
ProjectID: a.projectID,
146+
Opts: a.opts,
147+
Version: Version,
148+
}
149+
return remoteconfig.NewClient(ctx, conf)
150+
}
151+
141152
// NewApp creates a new App from the provided config and client options.
142153
//
143154
// If the client options contain a valid credential (a service account file, a refresh token

internal/internal.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ type MessagingConfig struct {
7474
Version string
7575
}
7676

77+
// RemoteConfigClientConfig represents the configuration of Firebase Remote Config
78+
type RemoteConfigClientConfig struct {
79+
Opts []option.ClientOption
80+
ProjectID string
81+
Version string
82+
}
83+
7784
// AppCheckConfig represents the configuration of App Check service.
7885
type AppCheckConfig struct {
7986
ProjectID string

messaging/messaging_batch.go

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"mime/multipart"
2828
"net/http"
2929
"net/textproto"
30-
"sync"
3130

3231
"firebase.google.com/go/v4/internal"
3332
)
@@ -165,53 +164,85 @@ func (c *fcmClient) sendEachInBatch(ctx context.Context, messages []*Message, dr
165164
return nil, fmt.Errorf("messages must not contain more than %d elements", maxMessages)
166165
}
167166

168-
var responses []*SendResponse = make([]*SendResponse, len(messages))
169-
var wg sync.WaitGroup
170-
171167
for idx, m := range messages {
172168
if err := validateMessage(m); err != nil {
173169
return nil, fmt.Errorf("invalid message at index %d: %v", idx, err)
174170
}
175-
wg.Add(1)
176-
go func(idx int, m *Message, dryRun bool, responses []*SendResponse) {
177-
defer wg.Done()
178-
var resp string
179-
var err error
180-
if dryRun {
181-
resp, err = c.SendDryRun(ctx, m)
182-
} else {
183-
resp, err = c.Send(ctx, m)
184-
}
185-
if err == nil {
186-
responses[idx] = &SendResponse{
187-
Success: true,
188-
MessageID: resp,
189-
}
190-
} else {
191-
responses[idx] = &SendResponse{
192-
Success: false,
193-
Error: err,
194-
}
195-
}
196-
}(idx, m, dryRun, responses)
197171
}
198-
// Wait for all SendDryRun/Send calls to finish
199-
wg.Wait()
172+
173+
const numWorkers = 50
174+
jobs := make(chan job, len(messages))
175+
results := make(chan result, len(messages))
176+
177+
responses := make([]*SendResponse, len(messages))
178+
179+
for w := 0; w < numWorkers; w++ {
180+
go worker(ctx, c, dryRun, jobs, results)
181+
}
182+
183+
for idx, m := range messages {
184+
jobs <- job{message: m, index: idx}
185+
}
186+
close(jobs)
187+
188+
for i := 0; i < len(messages); i++ {
189+
res := <-results
190+
responses[res.index] = res.response
191+
}
200192

201193
successCount := 0
194+
failureCount := 0
202195
for _, r := range responses {
203196
if r.Success {
204197
successCount++
198+
} else {
199+
failureCount++
205200
}
206201
}
207202

208203
return &BatchResponse{
209204
Responses: responses,
210205
SuccessCount: successCount,
211-
FailureCount: len(responses) - successCount,
206+
FailureCount: failureCount,
212207
}, nil
213208
}
214209

210+
type job struct {
211+
message *Message
212+
index int
213+
}
214+
215+
type result struct {
216+
response *SendResponse
217+
index int
218+
}
219+
220+
func worker(ctx context.Context, c *fcmClient, dryRun bool, jobs <-chan job, results chan<- result) {
221+
for j := range jobs {
222+
var respMsg string
223+
var err error
224+
if dryRun {
225+
respMsg, err = c.SendDryRun(ctx, j.message)
226+
} else {
227+
respMsg, err = c.Send(ctx, j.message)
228+
}
229+
230+
var sr *SendResponse
231+
if err == nil {
232+
sr = &SendResponse{
233+
Success: true,
234+
MessageID: respMsg,
235+
}
236+
} else {
237+
sr = &SendResponse{
238+
Success: false,
239+
Error: err,
240+
}
241+
}
242+
results <- result{response: sr, index: j.index}
243+
}
244+
}
245+
215246
// SendAll sends the messages in the given array via Firebase Cloud Messaging.
216247
//
217248
// The messages array may contain up to 500 messages. SendAll employs batching to send the entire

0 commit comments

Comments
 (0)