88import com .couchbase .lite .util .URIUtils ;
99import com .couchbase .lite .util .Utils ;
1010import com .fasterxml .jackson .core .JsonFactory ;
11+ import com .fasterxml .jackson .core .JsonParseException ;
1112import com .fasterxml .jackson .core .JsonParser ;
1213import com .fasterxml .jackson .core .JsonToken ;
1314
@@ -74,6 +75,7 @@ public class ChangeTracker implements Runnable {
7475 private boolean running = false ;
7576 private HttpUriRequest request ;
7677 protected ChangeTrackerBackoff backoff ;
78+ private long startTime = 0 ;
7779
7880
7981 public enum ChangeTrackerMode {
@@ -252,6 +254,8 @@ protected void runLoop() {
252254
253255 while (running ) {
254256
257+ startTime = System .currentTimeMillis ();
258+
255259 URL url = getChangesFeedURL ();
256260 if (usePOST ) {
257261 HttpPost postRequest = new HttpPost (url .toString ());
@@ -340,26 +344,40 @@ public void process(HttpRequest request, HttpContext context) throws HttpExcepti
340344 // NOTE: 2. HttpEntity.getContentLength() returns the number of bytes of the content, or a negative number if unknown.
341345 boolean responseOK = false ; // default value
342346 if (entity .getContentLength () != 0 ) {
343- Log .v (Log .TAG_CHANGE_TRACKER , "%s: readValue" , this );
344- Map <String , Object > fullBody = Manager .getObjectMapper ().readValue (inputStream , Map .class );
345- Log .v (Log .TAG_CHANGE_TRACKER , "%s: /readValue. fullBody: %s" , this , fullBody );
346- responseOK = receivedPollResponse (fullBody );
347+ try {
348+ Log .v (Log .TAG_CHANGE_TRACKER , "%s: readValue" , this );
349+ Map <String , Object > fullBody = Manager .getObjectMapper ().readValue (inputStream , Map .class );
350+ Log .v (Log .TAG_CHANGE_TRACKER , "%s: /readValue. fullBody: %s" , this , fullBody );
351+ responseOK = receivedPollResponse (fullBody );
352+ } catch (JsonParseException jpe ) {
353+ Log .w (Log .TAG_CHANGE_TRACKER , "%s: json parsing error; %s" , this , jpe .toString ());
354+ }
347355 }
348356 Log .v (Log .TAG_CHANGE_TRACKER , "%s: responseOK: %s" , this , responseOK );
349357
350- if (mode == ChangeTrackerMode .LongPoll && responseOK ) {
351-
358+ if (responseOK ) {
352359 // TODO: this logic is questionable, there's lots
353360 // TODO: of differences in the iOS changetracker code,
354361 client .changeTrackerCaughtUp ();
355-
356362 Log .v (Log .TAG_CHANGE_TRACKER , "%s: Starting new longpoll" , this );
357363 backoff .resetBackoff ();
358364 continue ;
359365 } else {
360- Log .d (Log .TAG_CHANGE_TRACKER , "%s: Change tracker calling stop (LongPoll)" , this );
361- client .changeTrackerFinished (this );
362- break ;
366+ long elapsed = (System .currentTimeMillis () - startTime ) / 1000 ;
367+ Log .w (Log .TAG_CHANGE_TRACKER , "%s: Longpoll connection closed (by proxy?) after %.1f sec" , this , elapsed );
368+ if (elapsed >= 30 ) {
369+ // Looks like the connection got closed by a proxy (like AWS' load balancer) while the
370+ // server was waiting for a change to send, due to lack of activity.
371+ // Lower the heartbeat time to work around this, and reconnect:
372+ this .heartBeatSeconds = Math .min (this .heartBeatSeconds , (int ) (elapsed * 0.75 ));
373+ Log .v (Log .TAG_CHANGE_TRACKER , "%s: Starting new longpoll" , this );
374+ backoff .resetBackoff ();
375+ continue ;
376+ } else {
377+ Log .d (Log .TAG_CHANGE_TRACKER , "%s: Change tracker calling stop (LongPoll)" , this );
378+ client .changeTrackerFinished (this );
379+ break ;
380+ }
363381 }
364382 } else { // one-shot replications
365383
@@ -379,7 +397,6 @@ public void process(HttpRequest request, HttpContext context) throws HttpExcepti
379397
380398 if (jp != null ) {
381399 jp .close ();
382- jp = null ;
383400 }
384401
385402 Log .v (Log .TAG_CHANGE_TRACKER , "%s: /readValue (oneshot)" , this );
@@ -403,14 +420,12 @@ public void process(HttpRequest request, HttpContext context) throws HttpExcepti
403420 }
404421 } catch (IOException e ) {
405422 }
406- inputStream = null ;
407423 if (entity != null ) {
408424 try {
409425 entity .consumeContent ();
410426 } catch (IOException e ) {
411427 }
412428 }
413- entity = null ;
414429 }
415430 }
416431 } catch (Exception e ) {
0 commit comments