void reschedule()

in src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java [504:583]


  void reschedule(PushOne pushOp, RetryReason reason) {
    synchronized (stateLock) {
      URIish uri = pushOp.getURI();
      PushOne pendingPushOp = getPendingPush(uri);

      if (pendingPushOp != null) {
        // There is one PushOp instance already pending to same URI.

        if (pendingPushOp.isRetrying()) {
          // The one pending is one already retrying, so it should
          // maintain it and add to it the refs of the one passed
          // as parameter to the method.

          // This scenario would happen if a PushOp has started running
          // and then before it failed due transport exception, another
          // one to same URI started. The first one would fail and would
          // be rescheduled, being present in pending list. When the
          // second one fails, it will also be rescheduled and then,
          // here, find out replication to its URI is already pending
          // for retry (blocking).
          pendingPushOp.addRefs(pushOp.getRefs());
          pendingPushOp.addStates(pushOp.getStates());
          pushOp.removeStates();

        } else {
          // The one pending is one that is NOT retrying, it was just
          // scheduled believing no problem would happen. The one pending
          // should be canceled, and this is done by setting its canceled
          // flag, removing it from pending list, and adding its refs to
          // the pushOp instance that should then, later, in this method,
          // be scheduled for retry.

          // Notice that the PushOp found pending will start running and,
          // when notifying it is starting (with pending lock protection),
          // it will see it was canceled and then it will do nothing with
          // pending list and it will not execute its run implementation.
          pendingPushOp.canceledByReplication();
          pending.remove(uri);

          pushOp.addRefs(pendingPushOp.getRefs());
          pushOp.addStates(pendingPushOp.getStates());
          pendingPushOp.removeStates();
        }
      }

      if (pendingPushOp == null || !pendingPushOp.isRetrying()) {
        pending.put(uri, pushOp);
        switch (reason) {
          case COLLISION:
            @SuppressWarnings("unused")
            ScheduledFuture<?> ignored =
                pool.schedule(pushOp, config.getRescheduleDelay(), TimeUnit.SECONDS);
            break;
          case TRANSPORT_ERROR:
          case REPOSITORY_MISSING:
          default:
            RemoteRefUpdate.Status status =
                RetryReason.REPOSITORY_MISSING.equals(reason)
                    ? NON_EXISTING
                    : REJECTED_OTHER_REASON;
            postReplicationFailedEvent(pushOp, status);
            if (pushOp.setToRetry()) {
              postReplicationScheduledEvent(pushOp);
              replicationTasksStorage.get().reset(pushOp);
              @SuppressWarnings("unused")
              ScheduledFuture<?> ignored2 =
                  pool.schedule(pushOp, config.getRetryDelay(), TimeUnit.MINUTES);
            } else {
              pushOp.canceledByReplication();
              pushOp.retryDone();
              pending.remove(uri);
              stateLog.error(
                  "Push to " + pushOp.getURI() + " cancelled after maximum number of retries",
                  pushOp.getStatesAsArray());
            }
            break;
        }
      }
    }
  }