@@ -14,6 +14,7 @@ public class Reporter {
1414 private var sendFirstBeacon = true // first beacon is sent all by itself, not in a batch
1515 private var slowSendStartTime : Date ?
1616 private var inSlowModeBeforeFlush = false
17+ private var lastFlushStartTime : Double ?
1718 private var flusher : BeaconFlusher ?
1819 internal var send : BeaconFlusher . Sender ?
1920 private let rateLimiter : ReporterRateLimiter
@@ -128,8 +129,34 @@ public class Reporter {
128129 }
129130 }
130131
132+ func canScheduleFlush( ) -> Bool {
133+ if flusher == nil {
134+ return true
135+ }
136+ if lastFlushStartTime == nil {
137+ return true
138+ }
139+
140+ var maxFlushingTimeAllowed = 10.0 // in seconds
141+ if isInSlowSendMode {
142+ maxFlushingTimeAllowed += session. configuration. slowSendInterval
143+ }
144+
145+ let diff = Date ( ) . timeIntervalSince1970 - lastFlushStartTime!
146+ if diff > maxFlushingTimeAllowed {
147+ // Previous flushing takes too long, force a new flush to prevent
148+ // too many beacons accumulated locally thus lead to beacon loss.
149+ session. logger. add ( " Previous flushing takes more than \( diff) seconds. Force another flushing now " )
150+ return true
151+ }
152+ return false
153+ }
154+
131155 func scheduleFlush( ) {
132156 guard !queue. items. isEmpty else { return }
157+
158+ if !canScheduleFlush( ) { return }
159+
133160 let start = Date ( )
134161 var debounce : TimeInterval
135162 let connectionType = networkUtility. connectionType
@@ -162,10 +189,14 @@ public class Reporter {
162189 config: session. configuration, queue: dispatchQueue,
163190 send: send) { [ weak self] result in
164191 guard let self = self else { return }
165- self . handle ( flushResult: result, start)
192+ self . dispatchQueue. async { [ weak self] in
193+ guard let self = self else { return }
194+ self . handle ( flushResult: result, start, fromBeaconFlusherCompletion: true )
195+ }
166196 }
167197 flusher. schedule ( )
168198 self . flusher = flusher
199+ lastFlushStartTime = Date ( ) . timeIntervalSince1970
169200 }
170201
171202 func runBackgroundFlush( ) {
@@ -180,7 +211,9 @@ public class Reporter {
180211 #endif
181212 }
182213
183- private func handle( flushResult: BeaconFlusher . Result , _ start: Date = Date ( ) ) {
214+ private func handle( flushResult: BeaconFlusher . Result ,
215+ _ start: Date = Date ( ) ,
216+ fromBeaconFlusherCompletion: Bool = false ) {
184217 let result : BeaconResult
185218 let errors = flushResult. errors
186219 let sent = flushResult. sentBeacons
@@ -201,16 +234,20 @@ public class Reporter {
201234 self . completionHandler. forEach { $0 ( result) }
202235 }
203236
204- if inSlowModeBeforeFlush {
205- // Another flush either resend 1 beacon (still in slow mode currently)
206- // or flush remaing beacons (got out of slow send mode already)
207- var msg : String
208- if isInSlowSendMode {
209- msg = " schedule flush to send 1 beacon in slow send mode "
210- } else {
211- msg = " flush all beacons after out of slow send mode "
237+ if fromBeaconFlusherCompletion {
238+ flusher = nil // mark this round flush done
239+ if inSlowModeBeforeFlush {
240+ // Another flush either resend 1 beacon (still in slow mode currently)
241+ // or flush remaining beacons (got out of slow send mode already)
242+ var msg : String
243+ if isInSlowSendMode {
244+ msg = " schedule flush to send 1 beacon in slow send mode "
245+ } else {
246+ msg = " flush all beacons after out of slow send mode "
247+ }
248+ session. logger. add ( msg)
212249 }
213- session . logger . add ( msg )
250+ // schedule next round flush
214251 scheduleFlush ( )
215252 }
216253 }
0 commit comments