Make retrying of requests generic (part 1)

Retrying of requests is currently implemented only for a subset of REST
endpoints (modifying change REST endpoints), but we would like to have
this functionality for all REST endpoints.

The retrying logic is currently specific to modifying change REST
endpoints since it's based on executing a ChangeAction with RetryHelper.
ChangeActions provide a BatchUpdate.Factory to their implementations,
but that's the only difference to the normal Action that can be retried.

If we use a normal Action for retrying requests (instead of a
ChangeAction) we can make the code that retries requests generic and use
it for all kind of REST endpoints. E.g. we could have one
RetryingRestModifyView class that can be used for all kind of modifying
REST endpoints instead of having one RetryingRestChangeModifyView for
change REST endpoints and one RetryingRestModifyView class for account,
group and project REST endpoints.

However implementing the retrying of requests in base classes of REST
endpoints also seems to be a bad idea since it means that retrying of
requests has to be implemented multiple times, once for each REST
endpoint interface that we have. At the moment we have 2 such base
classes, RetryingRestModifyView and RetryingRestCollectionModifyView. If
we would follow the current pattern we would need to add further base
classes, e.g. RetryingRestReadView, RetryingRestCollectionCreateView
etc.

This is why I want to remove these base classes and instead implement
the retrying of requests once directly in RestApiServlet.

Implementing the retrying of requests in RestApiServlet also has further
advantages:

- In case of auto-retry-with-trace we do not need a complicated way to
  return the trace ID from the REST endpoint implementation back to
  RestApiServlet (means we can simplify the existing code).
- In RestApiServlet we have more information about the REST endpoint
  available and may include this information into traces on auto-retry.

Implementating all of this needs to touch a lot of classes. This is why
for easier reviews it's done in multiple steps:

1. Make retry logic in RetryingRestModifyView generic so that it can be
   used for all kind of requests (this change):
   This means we will provide a normal Action to the RetryHelper,
   instead of a ChangeAction. The disadvantage of this is that now all
   modifying change REST endpoints need to get the BatchUpdate.Factory
   injected. But this doesn't seem to be worse than the current
   requirement of injecting RetryHelper. Once the retrying is
   implemented in RestApiServlet (see step 3) the modifying change REST
   endpoints no longer need to get the RetryHelper injected. Hence after
   all we just switch from injecting RetryHelper to injecting
   BatchUpdate.Factory, which doesn't make a big difference. Some of the
   REST endpoints that extended RetryingRestModifyView actually even
   don't need a BatchUpdate.Factory, so for them the code actually gets
   simpler.
   We are now also using a dedicated action type for retrying REST
   requests. This allows use to differentiate between retries of whole
   requests vs retries of small actions when looking at the retry
   metrics.

2. Make retry logic in RetryingRestCollectionModifyView generic so that
   it can be used for all kind of requests.

3. Move the retrying logic into RestApiServlet:
   This means we can now delete RetryingRestModifyView and
   RetryingRestCollectionModifyView.

4. Remove code complications that were needed to return the trace ID
   from a REST endpoint to RestApiServlet in case of
   auto-retry-with-trace.

5. Enhance traces that are created on auto-retry:
   Include information that is normally logged by RestApiServlet if a
   request is traced (e.g. the REST endpoint URL, calling user, etc.)

6. Implement retry and auto-tracing for non-modifyable REST endpoints.

Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: I3edd3673bf29428db2eb1ceac782da059ec58953
Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
Edwin Kempin
2019-10-22 08:56:09 +02:00
committed by David Pursehouse
parent e68bc52123
commit d412bc8e2d
36 changed files with 163 additions and 96 deletions

View File

@@ -48,6 +48,7 @@ public class Abandon extends RetryingRestModifyView<ChangeResource, AbandonInput
implements UiAction<ChangeResource> {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final BatchUpdate.Factory updateFactory;
private final ChangeJson.Factory json;
private final AbandonOp.Factory abandonOpFactory;
private final NotifyResolver notifyResolver;
@@ -55,12 +56,14 @@ public class Abandon extends RetryingRestModifyView<ChangeResource, AbandonInput
@Inject
Abandon(
BatchUpdate.Factory updateFactory,
ChangeJson.Factory json,
RetryHelper retryHelper,
AbandonOp.Factory abandonOpFactory,
NotifyResolver notifyResolver,
PatchSetUtil patchSetUtil) {
super(retryHelper);
this.updateFactory = updateFactory;
this.json = json;
this.abandonOpFactory = abandonOpFactory;
this.notifyResolver = notifyResolver;
@@ -68,8 +71,7 @@ public class Abandon extends RetryingRestModifyView<ChangeResource, AbandonInput
}
@Override
protected Response<ChangeInfo> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, AbandonInput input)
protected Response<ChangeInfo> applyImpl(ChangeResource rsrc, AbandonInput input)
throws RestApiException, UpdateException, PermissionBackendException, IOException,
ConfigInvalidException {
// Not allowed to abandon if the current patch set is locked.

View File

@@ -54,6 +54,7 @@ public class CherryPick
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final PermissionBackend permissionBackend;
private final BatchUpdate.Factory updateFactory;
private final CherryPickChange cherryPickChange;
private final ChangeJson.Factory json;
private final ContributorAgreementsChecker contributorAgreements;
@@ -61,14 +62,16 @@ public class CherryPick
@Inject
CherryPick(
PermissionBackend permissionBackend,
RetryHelper retryHelper,
PermissionBackend permissionBackend,
BatchUpdate.Factory updateFactory,
CherryPickChange cherryPickChange,
ChangeJson.Factory json,
ContributorAgreementsChecker contributorAgreements,
ProjectCache projectCache) {
super(retryHelper);
this.permissionBackend = permissionBackend;
this.updateFactory = updateFactory;
this.cherryPickChange = cherryPickChange;
this.json = json;
this.contributorAgreements = contributorAgreements;
@@ -76,8 +79,7 @@ public class CherryPick
}
@Override
public Response<CherryPickChangeInfo> applyImpl(
BatchUpdate.Factory updateFactory, RevisionResource rsrc, CherryPickInput input)
public Response<CherryPickChangeInfo> applyImpl(RevisionResource rsrc, CherryPickInput input)
throws IOException, UpdateException, RestApiException, PermissionBackendException,
ConfigInvalidException, NoSuchProjectException {
input.parent = input.parent == null ? 1 : input.parent;

View File

@@ -48,6 +48,7 @@ import org.eclipse.jgit.errors.ConfigInvalidException;
public class CherryPickCommit
extends RetryingRestModifyView<CommitResource, CherryPickInput, CherryPickChangeInfo> {
private final PermissionBackend permissionBackend;
private final BatchUpdate.Factory updateFactory;
private final Provider<CurrentUser> user;
private final CherryPickChange cherryPickChange;
private final ChangeJson.Factory json;
@@ -56,13 +57,15 @@ public class CherryPickCommit
@Inject
CherryPickCommit(
RetryHelper retryHelper,
PermissionBackend permissionBackend,
BatchUpdate.Factory updateFactory,
Provider<CurrentUser> user,
CherryPickChange cherryPickChange,
ChangeJson.Factory json,
PermissionBackend permissionBackend,
ContributorAgreementsChecker contributorAgreements) {
super(retryHelper);
this.permissionBackend = permissionBackend;
this.updateFactory = updateFactory;
this.user = user;
this.cherryPickChange = cherryPickChange;
this.json = json;
@@ -70,8 +73,7 @@ public class CherryPickCommit
}
@Override
public Response<CherryPickChangeInfo> applyImpl(
BatchUpdate.Factory updateFactory, CommitResource rsrc, CherryPickInput input)
public Response<CherryPickChangeInfo> applyImpl(CommitResource rsrc, CherryPickInput input)
throws IOException, UpdateException, RestApiException, PermissionBackendException,
ConfigInvalidException, NoSuchProjectException {
String destination = Strings.nullToEmpty(input.destination).trim();

View File

@@ -48,6 +48,7 @@ import java.util.Collections;
@Singleton
public class CreateDraftComment
extends RetryingRestModifyView<RevisionResource, DraftInput, CommentInfo> {
private final BatchUpdate.Factory updateFactory;
private final Provider<CommentJson> commentJson;
private final CommentsUtil commentsUtil;
private final PatchSetUtil psUtil;
@@ -56,11 +57,13 @@ public class CreateDraftComment
@Inject
CreateDraftComment(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
Provider<CommentJson> commentJson,
CommentsUtil commentsUtil,
PatchSetUtil psUtil,
PatchListCache patchListCache) {
super(retryHelper);
this.updateFactory = updateFactory;
this.commentJson = commentJson;
this.commentsUtil = commentsUtil;
this.psUtil = psUtil;
@@ -68,8 +71,7 @@ public class CreateDraftComment
}
@Override
protected Response<CommentInfo> applyImpl(
BatchUpdate.Factory updateFactory, RevisionResource rsrc, DraftInput in)
protected Response<CommentInfo> applyImpl(RevisionResource rsrc, DraftInput in)
throws RestApiException, UpdateException, PermissionBackendException {
if (Strings.isNullOrEmpty(in.path)) {
throw new BadRequestException("path must be non-empty");

View File

@@ -77,6 +77,7 @@ import org.eclipse.jgit.util.ChangeIdUtil;
@Singleton
public class CreateMergePatchSet
extends RetryingRestModifyView<ChangeResource, MergePatchSetInput, ChangeInfo> {
private final BatchUpdate.Factory updateFactory;
private final GitRepositoryManager gitManager;
private final CommitsCollection commits;
private final TimeZone serverTimeZone;
@@ -91,6 +92,7 @@ public class CreateMergePatchSet
@Inject
CreateMergePatchSet(
BatchUpdate.Factory updateFactory,
GitRepositoryManager gitManager,
CommitsCollection commits,
@GerritPersonIdent PersonIdent myIdent,
@@ -104,6 +106,7 @@ public class CreateMergePatchSet
ChangeFinder changeFinder,
PermissionBackend permissionBackend) {
super(retryHelper);
this.updateFactory = updateFactory;
this.gitManager = gitManager;
this.commits = commits;
this.serverTimeZone = myIdent.getTimeZone();
@@ -118,8 +121,7 @@ public class CreateMergePatchSet
}
@Override
protected Response<ChangeInfo> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, MergePatchSetInput in)
protected Response<ChangeInfo> applyImpl(ChangeResource rsrc, MergePatchSetInput in)
throws IOException, RestApiException, UpdateException, PermissionBackendException {
// Not allowed to create a new patch set if the current patch set is locked.
psUtil.checkPatchSetNotLocked(rsrc.getNotes());

View File

@@ -43,7 +43,7 @@ import com.google.inject.Singleton;
@Singleton
public class DeleteAssignee extends RetryingRestModifyView<ChangeResource, Input, AccountInfo> {
private final BatchUpdate.Factory updateFactory;
private final ChangeMessagesUtil cmUtil;
private final AssigneeChanged assigneeChanged;
private final IdentifiedUser.GenericFactory userFactory;
@@ -52,11 +52,13 @@ public class DeleteAssignee extends RetryingRestModifyView<ChangeResource, Input
@Inject
DeleteAssignee(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
ChangeMessagesUtil cmUtil,
AssigneeChanged assigneeChanged,
IdentifiedUser.GenericFactory userFactory,
AccountLoader.Factory accountLoaderFactory) {
super(retryHelper);
this.updateFactory = updateFactory;
this.cmUtil = cmUtil;
this.assigneeChanged = assigneeChanged;
this.userFactory = userFactory;
@@ -64,8 +66,7 @@ public class DeleteAssignee extends RetryingRestModifyView<ChangeResource, Input
}
@Override
protected Response<AccountInfo> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
protected Response<AccountInfo> applyImpl(ChangeResource rsrc, Input input)
throws RestApiException, UpdateException, PermissionBackendException {
rsrc.permissions().check(ChangePermission.EDIT_ASSIGNEE);

View File

@@ -38,18 +38,21 @@ import com.google.inject.Singleton;
@Singleton
public class DeleteChange extends RetryingRestModifyView<ChangeResource, Input, Object>
implements UiAction<ChangeResource> {
private final BatchUpdate.Factory updateFactory;
private final DeleteChangeOp.Factory opFactory;
@Inject
public DeleteChange(RetryHelper retryHelper, DeleteChangeOp.Factory opFactory) {
public DeleteChange(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
DeleteChangeOp.Factory opFactory) {
super(retryHelper);
this.updateFactory = updateFactory;
this.opFactory = opFactory;
}
@Override
protected Response<Object> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
protected Response<Object> applyImpl(ChangeResource rsrc, Input input)
throws RestApiException, UpdateException, PermissionBackendException {
if (!isChangeDeletable(rsrc)) {
throw new MethodNotAllowedException("delete not permitted");

View File

@@ -58,6 +58,7 @@ public class DeleteChangeMessage
private final Provider<CurrentUser> userProvider;
private final PermissionBackend permissionBackend;
private final BatchUpdate.Factory updateFactory;
private final ChangeMessagesUtil changeMessagesUtil;
private final AccountLoader.Factory accountLoaderFactory;
private final ChangeNotes.Factory notesFactory;
@@ -66,6 +67,7 @@ public class DeleteChangeMessage
public DeleteChangeMessage(
Provider<CurrentUser> userProvider,
PermissionBackend permissionBackend,
BatchUpdate.Factory updateFactory,
ChangeMessagesUtil changeMessagesUtil,
AccountLoader.Factory accountLoaderFactory,
ChangeNotes.Factory notesFactory,
@@ -73,6 +75,7 @@ public class DeleteChangeMessage
super(retryHelper);
this.userProvider = userProvider;
this.permissionBackend = permissionBackend;
this.updateFactory = updateFactory;
this.changeMessagesUtil = changeMessagesUtil;
this.accountLoaderFactory = accountLoaderFactory;
this.notesFactory = notesFactory;
@@ -80,9 +83,7 @@ public class DeleteChangeMessage
@Override
public Response<ChangeMessageInfo> applyImpl(
BatchUpdate.Factory updateFactory,
ChangeMessageResource resource,
DeleteChangeMessageInput input)
ChangeMessageResource resource, DeleteChangeMessageInput input)
throws RestApiException, PermissionBackendException, UpdateException, IOException {
CurrentUser user = userProvider.get();
permissionBackend.user(user).check(GlobalPermission.ADMINISTRATE_SERVER);

View File

@@ -51,29 +51,31 @@ public class DeleteComment
private final Provider<CurrentUser> userProvider;
private final PermissionBackend permissionBackend;
private final BatchUpdate.Factory updateFactory;
private final CommentsUtil commentsUtil;
private final Provider<CommentJson> commentJson;
private final ChangeNotes.Factory notesFactory;
@Inject
public DeleteComment(
RetryHelper retryHelper,
Provider<CurrentUser> userProvider,
PermissionBackend permissionBackend,
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
CommentsUtil commentsUtil,
Provider<CommentJson> commentJson,
ChangeNotes.Factory notesFactory) {
super(retryHelper);
this.userProvider = userProvider;
this.permissionBackend = permissionBackend;
this.updateFactory = updateFactory;
this.commentsUtil = commentsUtil;
this.commentJson = commentJson;
this.notesFactory = notesFactory;
}
@Override
public Response<CommentInfo> applyImpl(
BatchUpdate.Factory batchUpdateFactory, CommentResource rsrc, DeleteCommentInput input)
public Response<CommentInfo> applyImpl(CommentResource rsrc, DeleteCommentInput input)
throws RestApiException, IOException, ConfigInvalidException, PermissionBackendException,
UpdateException {
CurrentUser user = userProvider.get();
@@ -86,8 +88,7 @@ public class DeleteComment
String newMessage = getCommentNewMessage(user.asIdentifiedUser().getName(), input.reason);
DeleteCommentOp deleteCommentOp = new DeleteCommentOp(rsrc, newMessage);
try (BatchUpdate batchUpdate =
batchUpdateFactory.create(
rsrc.getRevisionResource().getProject(), user, TimeUtil.nowTs())) {
updateFactory.create(rsrc.getRevisionResource().getProject(), user, TimeUtil.nowTs())) {
batchUpdate.addOp(rsrc.getRevisionResource().getChange().getId(), deleteCommentOp).execute();
}

View File

@@ -43,26 +43,27 @@ import java.util.Optional;
@Singleton
public class DeleteDraftComment
extends RetryingRestModifyView<DraftCommentResource, Input, CommentInfo> {
private final BatchUpdate.Factory updateFactory;
private final CommentsUtil commentsUtil;
private final PatchSetUtil psUtil;
private final PatchListCache patchListCache;
@Inject
DeleteDraftComment(
BatchUpdate.Factory updateFactory,
CommentsUtil commentsUtil,
PatchSetUtil psUtil,
RetryHelper retryHelper,
PatchListCache patchListCache) {
super(retryHelper);
this.updateFactory = updateFactory;
this.commentsUtil = commentsUtil;
this.psUtil = psUtil;
this.patchListCache = patchListCache;
}
@Override
protected Response<CommentInfo> applyImpl(
BatchUpdate.Factory updateFactory, DraftCommentResource rsrc, Input input)
protected Response<CommentInfo> applyImpl(DraftCommentResource rsrc, Input input)
throws RestApiException, UpdateException {
try (BatchUpdate bu =
updateFactory.create(rsrc.getChange().getProject(), rsrc.getUser(), TimeUtil.nowTs())) {

View File

@@ -39,21 +39,23 @@ import com.google.inject.Singleton;
public class DeletePrivate
extends RetryingRestModifyView<ChangeResource, InputWithMessage, String> {
private final PermissionBackend permissionBackend;
private final BatchUpdate.Factory updateFactory;
private final SetPrivateOp.Factory setPrivateOpFactory;
@Inject
DeletePrivate(
RetryHelper retryHelper,
PermissionBackend permissionBackend,
BatchUpdate.Factory updateFactory,
SetPrivateOp.Factory setPrivateOpFactory) {
super(retryHelper);
this.permissionBackend = permissionBackend;
this.updateFactory = updateFactory;
this.setPrivateOpFactory = setPrivateOpFactory;
}
@Override
protected Response<String> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, @Nullable InputWithMessage input)
protected Response<String> applyImpl(ChangeResource rsrc, @Nullable InputWithMessage input)
throws RestApiException, UpdateException {
if (!canDeletePrivate(rsrc).value()) {
throw new AuthException("not allowed to unmark private");

View File

@@ -20,6 +20,7 @@ import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.SetPrivateOp;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.RetryHelper;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -30,8 +31,9 @@ public class DeletePrivateByPost extends DeletePrivate implements UiAction<Chang
DeletePrivateByPost(
RetryHelper retryHelper,
PermissionBackend permissionBackend,
BatchUpdate.Factory updateFactory,
SetPrivateOp.Factory setPrivateOpFactory) {
super(retryHelper, permissionBackend, setPrivateOpFactory);
super(retryHelper, permissionBackend, updateFactory, setPrivateOpFactory);
}
@Override

View File

@@ -35,23 +35,24 @@ import com.google.inject.Singleton;
@Singleton
public class DeleteReviewer
extends RetryingRestModifyView<ReviewerResource, DeleteReviewerInput, Object> {
private final BatchUpdate.Factory updateFactory;
private final DeleteReviewerOp.Factory deleteReviewerOpFactory;
private final DeleteReviewerByEmailOp.Factory deleteReviewerByEmailOpFactory;
@Inject
DeleteReviewer(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
DeleteReviewerOp.Factory deleteReviewerOpFactory,
DeleteReviewerByEmailOp.Factory deleteReviewerByEmailOpFactory) {
super(retryHelper);
this.updateFactory = updateFactory;
this.deleteReviewerOpFactory = deleteReviewerOpFactory;
this.deleteReviewerByEmailOpFactory = deleteReviewerByEmailOpFactory;
}
@Override
protected Response<Object> applyImpl(
BatchUpdate.Factory updateFactory, ReviewerResource rsrc, DeleteReviewerInput input)
protected Response<Object> applyImpl(ReviewerResource rsrc, DeleteReviewerInput input)
throws RestApiException, UpdateException {
if (input == null) {
input = new DeleteReviewerInput();

View File

@@ -67,6 +67,7 @@ import org.eclipse.jgit.errors.ConfigInvalidException;
public class DeleteVote extends RetryingRestModifyView<VoteResource, DeleteVoteInput, Object> {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final BatchUpdate.Factory updateFactory;
private final ApprovalsUtil approvalsUtil;
private final PatchSetUtil psUtil;
private final ChangeMessagesUtil cmUtil;
@@ -80,6 +81,7 @@ public class DeleteVote extends RetryingRestModifyView<VoteResource, DeleteVoteI
@Inject
DeleteVote(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
ApprovalsUtil approvalsUtil,
PatchSetUtil psUtil,
ChangeMessagesUtil cmUtil,
@@ -90,6 +92,7 @@ public class DeleteVote extends RetryingRestModifyView<VoteResource, DeleteVoteI
RemoveReviewerControl removeReviewerControl,
ProjectCache projectCache) {
super(retryHelper);
this.updateFactory = updateFactory;
this.approvalsUtil = approvalsUtil;
this.psUtil = psUtil;
this.cmUtil = cmUtil;
@@ -102,8 +105,7 @@ public class DeleteVote extends RetryingRestModifyView<VoteResource, DeleteVoteI
}
@Override
protected Response<Object> applyImpl(
BatchUpdate.Factory updateFactory, VoteResource rsrc, DeleteVoteInput input)
protected Response<Object> applyImpl(VoteResource rsrc, DeleteVoteInput input)
throws RestApiException, UpdateException, IOException, ConfigInvalidException {
if (input == null) {
input = new DeleteVoteInput();

View File

@@ -22,7 +22,6 @@ import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.inject.Inject;
@@ -42,8 +41,7 @@ public class Index extends RetryingRestModifyView<ChangeResource, Input, Object>
}
@Override
protected Response<Object> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
protected Response<Object> applyImpl(ChangeResource rsrc, Input input)
throws IOException, AuthException, PermissionBackendException {
permissionBackend.currentUser().check(GlobalPermission.MAINTAIN_SERVER);
indexer.index(rsrc.getChange());

View File

@@ -81,6 +81,7 @@ public class Move extends RetryingRestModifyView<ChangeResource, MoveInput, Chan
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final PermissionBackend permissionBackend;
private final BatchUpdate.Factory updateFactory;
private final ChangeJson.Factory json;
private final GitRepositoryManager repoManager;
private final Provider<InternalChangeQuery> queryProvider;
@@ -93,6 +94,7 @@ public class Move extends RetryingRestModifyView<ChangeResource, MoveInput, Chan
@Inject
Move(
PermissionBackend permissionBackend,
BatchUpdate.Factory updateFactory,
ChangeJson.Factory json,
GitRepositoryManager repoManager,
Provider<InternalChangeQuery> queryProvider,
@@ -104,6 +106,7 @@ public class Move extends RetryingRestModifyView<ChangeResource, MoveInput, Chan
@GerritServerConfig Config gerritConfig) {
super(retryHelper);
this.permissionBackend = permissionBackend;
this.updateFactory = updateFactory;
this.json = json;
this.repoManager = repoManager;
this.queryProvider = queryProvider;
@@ -115,8 +118,7 @@ public class Move extends RetryingRestModifyView<ChangeResource, MoveInput, Chan
}
@Override
protected Response<ChangeInfo> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, MoveInput input)
protected Response<ChangeInfo> applyImpl(ChangeResource rsrc, MoveInput input)
throws RestApiException, UpdateException, PermissionBackendException, IOException {
if (!moveEnabled) {
// This will be removed with the above config once we reach consensus for the move change

View File

@@ -35,17 +35,21 @@ import com.google.inject.Singleton;
public class PostHashtags
extends RetryingRestModifyView<ChangeResource, HashtagsInput, ImmutableSortedSet<String>>
implements UiAction<ChangeResource> {
private final BatchUpdate.Factory updateFactory;
private final SetHashtagsOp.Factory hashtagsFactory;
@Inject
PostHashtags(RetryHelper retryHelper, SetHashtagsOp.Factory hashtagsFactory) {
PostHashtags(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
SetHashtagsOp.Factory hashtagsFactory) {
super(retryHelper);
this.updateFactory = updateFactory;
this.hashtagsFactory = hashtagsFactory;
}
@Override
protected Response<ImmutableSortedSet<String>> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource req, HashtagsInput input)
protected Response<ImmutableSortedSet<String>> applyImpl(ChangeResource req, HashtagsInput input)
throws RestApiException, UpdateException, PermissionBackendException {
req.permissions().check(ChangePermission.EDIT_HASHTAGS);

View File

@@ -43,6 +43,7 @@ import org.eclipse.jgit.lib.Config;
public class PostPrivate extends RetryingRestModifyView<ChangeResource, InputWithMessage, String>
implements UiAction<ChangeResource> {
private final PermissionBackend permissionBackend;
private final BatchUpdate.Factory updateFactory;
private final SetPrivateOp.Factory setPrivateOpFactory;
private final boolean disablePrivateChanges;
@@ -50,17 +51,18 @@ public class PostPrivate extends RetryingRestModifyView<ChangeResource, InputWit
PostPrivate(
RetryHelper retryHelper,
PermissionBackend permissionBackend,
BatchUpdate.Factory updateFactory,
SetPrivateOp.Factory setPrivateOpFactory,
@GerritServerConfig Config config) {
super(retryHelper);
this.permissionBackend = permissionBackend;
this.updateFactory = updateFactory;
this.setPrivateOpFactory = setPrivateOpFactory;
this.disablePrivateChanges = config.getBoolean("change", null, "disablePrivateChanges", false);
}
@Override
public Response<String> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, InputWithMessage input)
public Response<String> applyImpl(ChangeResource rsrc, InputWithMessage input)
throws RestApiException, UpdateException {
if (disablePrivateChanges) {
throw new MethodNotAllowedException("private changes are disabled");

View File

@@ -163,6 +163,7 @@ public class PostReview
private static final Gson GSON = OutputFormat.JSON_COMPACT.newGson();
private static final int DEFAULT_ROBOT_COMMENT_SIZE_LIMIT_IN_BYTES = 1024 * 1024;
private final BatchUpdate.Factory updateFactory;
private final ChangeResource.Factory changeResourceFactory;
private final ChangeData.Factory changeDataFactory;
private final ApprovalsUtil approvalsUtil;
@@ -187,6 +188,7 @@ public class PostReview
@Inject
PostReview(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
ChangeResource.Factory changeResourceFactory,
ChangeData.Factory changeDataFactory,
ApprovalsUtil approvalsUtil,
@@ -207,6 +209,7 @@ public class PostReview
PermissionBackend permissionBackend,
PluginSetContext<CommentValidator> commentValidators) {
super(retryHelper);
this.updateFactory = updateFactory;
this.changeResourceFactory = changeResourceFactory;
this.changeDataFactory = changeDataFactory;
this.commentsUtil = commentsUtil;
@@ -230,15 +233,13 @@ public class PostReview
}
@Override
protected Response<ReviewResult> applyImpl(
BatchUpdate.Factory updateFactory, RevisionResource revision, ReviewInput input)
protected Response<ReviewResult> applyImpl(RevisionResource revision, ReviewInput input)
throws RestApiException, UpdateException, IOException, PermissionBackendException,
ConfigInvalidException, PatchListNotAvailableException {
return apply(updateFactory, revision, input, TimeUtil.nowTs());
return apply(revision, input, TimeUtil.nowTs());
}
public Response<ReviewResult> apply(
BatchUpdate.Factory updateFactory, RevisionResource revision, ReviewInput input, Timestamp ts)
public Response<ReviewResult> apply(RevisionResource revision, ReviewInput input, Timestamp ts)
throws RestApiException, UpdateException, IOException, PermissionBackendException,
ConfigInvalidException, PatchListNotAvailableException {
// Respect timestamp, but truncate at change created-on time.

View File

@@ -40,6 +40,7 @@ import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class PublishChangeEdit
extends RetryingRestModifyView<ChangeResource, PublishChangeEditInput, Object> {
private final BatchUpdate.Factory updateFactory;
private final ChangeEditUtil editUtil;
private final NotifyResolver notifyResolver;
private final ContributorAgreementsChecker contributorAgreementsChecker;
@@ -47,18 +48,19 @@ public class PublishChangeEdit
@Inject
PublishChangeEdit(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
ChangeEditUtil editUtil,
NotifyResolver notifyResolver,
ContributorAgreementsChecker contributorAgreementsChecker) {
super(retryHelper);
this.updateFactory = updateFactory;
this.editUtil = editUtil;
this.notifyResolver = notifyResolver;
this.contributorAgreementsChecker = contributorAgreementsChecker;
}
@Override
protected Response<Object> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, PublishChangeEditInput in)
protected Response<Object> applyImpl(ChangeResource rsrc, PublishChangeEditInput in)
throws IOException, RestApiException, UpdateException, ConfigInvalidException,
NoSuchProjectException {
contributorAgreementsChecker.check(rsrc.getProject(), rsrc.getUser());

View File

@@ -51,6 +51,7 @@ import org.eclipse.jgit.errors.ConfigInvalidException;
public class PutAssignee extends RetryingRestModifyView<ChangeResource, AssigneeInput, AccountInfo>
implements UiAction<ChangeResource> {
private final BatchUpdate.Factory updateFactory;
private final AccountResolver accountResolver;
private final SetAssigneeOp.Factory assigneeFactory;
private final ReviewerAdder reviewerAdder;
@@ -60,6 +61,7 @@ public class PutAssignee extends RetryingRestModifyView<ChangeResource, Assignee
@Inject
PutAssignee(
BatchUpdate.Factory updateFactory,
AccountResolver accountResolver,
SetAssigneeOp.Factory assigneeFactory,
RetryHelper retryHelper,
@@ -68,6 +70,7 @@ public class PutAssignee extends RetryingRestModifyView<ChangeResource, Assignee
PermissionBackend permissionBackend,
ApprovalsUtil approvalsUtil) {
super(retryHelper);
this.updateFactory = updateFactory;
this.accountResolver = accountResolver;
this.assigneeFactory = assigneeFactory;
this.reviewerAdder = reviewerAdder;
@@ -77,8 +80,7 @@ public class PutAssignee extends RetryingRestModifyView<ChangeResource, Assignee
}
@Override
protected Response<AccountInfo> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, AssigneeInput input)
protected Response<AccountInfo> applyImpl(ChangeResource rsrc, AssigneeInput input)
throws RestApiException, UpdateException, IOException, PermissionBackendException,
ConfigInvalidException {
rsrc.permissions().check(ChangePermission.EDIT_ASSIGNEE);

View File

@@ -41,19 +41,24 @@ import com.google.inject.Singleton;
public class PutDescription
extends RetryingRestModifyView<RevisionResource, DescriptionInput, String>
implements UiAction<RevisionResource> {
private final BatchUpdate.Factory updateFactory;
private final ChangeMessagesUtil cmUtil;
private final PatchSetUtil psUtil;
@Inject
PutDescription(ChangeMessagesUtil cmUtil, RetryHelper retryHelper, PatchSetUtil psUtil) {
PutDescription(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
ChangeMessagesUtil cmUtil,
PatchSetUtil psUtil) {
super(retryHelper);
this.updateFactory = updateFactory;
this.cmUtil = cmUtil;
this.psUtil = psUtil;
}
@Override
protected Response<String> applyImpl(
BatchUpdate.Factory updateFactory, RevisionResource rsrc, DescriptionInput input)
protected Response<String> applyImpl(RevisionResource rsrc, DescriptionInput input)
throws UpdateException, RestApiException, PermissionBackendException {
rsrc.permissions().check(ChangePermission.EDIT_DESCRIPTION);

View File

@@ -49,7 +49,7 @@ import java.util.Optional;
@Singleton
public class PutDraftComment
extends RetryingRestModifyView<DraftCommentResource, DraftInput, CommentInfo> {
private final BatchUpdate.Factory updateFactory;
private final DeleteDraftComment delete;
private final CommentsUtil commentsUtil;
private final PatchSetUtil psUtil;
@@ -58,13 +58,15 @@ public class PutDraftComment
@Inject
PutDraftComment(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
DeleteDraftComment delete,
CommentsUtil commentsUtil,
PatchSetUtil psUtil,
RetryHelper retryHelper,
Provider<CommentJson> commentJson,
PatchListCache patchListCache) {
super(retryHelper);
this.updateFactory = updateFactory;
this.delete = delete;
this.commentsUtil = commentsUtil;
this.psUtil = psUtil;
@@ -73,11 +75,10 @@ public class PutDraftComment
}
@Override
protected Response<CommentInfo> applyImpl(
BatchUpdate.Factory updateFactory, DraftCommentResource rsrc, DraftInput in)
protected Response<CommentInfo> applyImpl(DraftCommentResource rsrc, DraftInput in)
throws RestApiException, UpdateException, PermissionBackendException {
if (in == null || in.message == null || in.message.trim().isEmpty()) {
return delete.applyImpl(updateFactory, rsrc, null);
return delete.applyImpl(rsrc, null);
} else if (in.id != null && !rsrc.getId().equals(in.id)) {
throw new BadRequestException("id must match URL");
} else if (in.line != null && in.line < 0) {

View File

@@ -63,6 +63,7 @@ import org.eclipse.jgit.revwalk.RevWalk;
@Singleton
public class PutMessage extends RetryingRestModifyView<ChangeResource, CommitMessageInput, String> {
private final BatchUpdate.Factory updateFactory;
private final GitRepositoryManager repositoryManager;
private final Provider<CurrentUser> userProvider;
private final TimeZone tz;
@@ -75,6 +76,7 @@ public class PutMessage extends RetryingRestModifyView<ChangeResource, CommitMes
@Inject
PutMessage(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
GitRepositoryManager repositoryManager,
Provider<CurrentUser> userProvider,
PatchSetInserter.Factory psInserterFactory,
@@ -84,6 +86,7 @@ public class PutMessage extends RetryingRestModifyView<ChangeResource, CommitMes
NotifyResolver notifyResolver,
ProjectCache projectCache) {
super(retryHelper);
this.updateFactory = updateFactory;
this.repositoryManager = repositoryManager;
this.userProvider = userProvider;
this.psInserterFactory = psInserterFactory;
@@ -95,8 +98,7 @@ public class PutMessage extends RetryingRestModifyView<ChangeResource, CommitMes
}
@Override
protected Response<String> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource resource, CommitMessageInput input)
protected Response<String> applyImpl(ChangeResource resource, CommitMessageInput input)
throws IOException, RestApiException, UpdateException, PermissionBackendException,
ConfigInvalidException {
PatchSet ps = psUtil.current(resource.getNotes());

View File

@@ -43,19 +43,24 @@ import com.google.inject.Singleton;
@Singleton
public class PutTopic extends RetryingRestModifyView<ChangeResource, TopicInput, String>
implements UiAction<ChangeResource> {
private final BatchUpdate.Factory updateFactory;
private final ChangeMessagesUtil cmUtil;
private final TopicEdited topicEdited;
@Inject
PutTopic(ChangeMessagesUtil cmUtil, RetryHelper retryHelper, TopicEdited topicEdited) {
PutTopic(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
ChangeMessagesUtil cmUtil,
TopicEdited topicEdited) {
super(retryHelper);
this.updateFactory = updateFactory;
this.cmUtil = cmUtil;
this.topicEdited = topicEdited;
}
@Override
protected Response<String> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource req, TopicInput input)
protected Response<String> applyImpl(ChangeResource req, TopicInput input)
throws UpdateException, RestApiException, PermissionBackendException {
req.permissions().check(ChangePermission.EDIT_TOPIC_NAME);

View File

@@ -70,6 +70,7 @@ public class Rebase extends RetryingRestModifyView<RevisionResource, RebaseInput
private static final ImmutableSet<ListChangesOption> OPTIONS =
Sets.immutableEnumSet(ListChangesOption.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT);
private final BatchUpdate.Factory updateFactory;
private final GitRepositoryManager repoManager;
private final RebaseChangeOp.Factory rebaseFactory;
private final RebaseUtil rebaseUtil;
@@ -81,6 +82,7 @@ public class Rebase extends RetryingRestModifyView<RevisionResource, RebaseInput
@Inject
public Rebase(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
GitRepositoryManager repoManager,
RebaseChangeOp.Factory rebaseFactory,
RebaseUtil rebaseUtil,
@@ -89,6 +91,7 @@ public class Rebase extends RetryingRestModifyView<RevisionResource, RebaseInput
ProjectCache projectCache,
PatchSetUtil patchSetUtil) {
super(retryHelper);
this.updateFactory = updateFactory;
this.repoManager = repoManager;
this.rebaseFactory = rebaseFactory;
this.rebaseUtil = rebaseUtil;
@@ -99,8 +102,7 @@ public class Rebase extends RetryingRestModifyView<RevisionResource, RebaseInput
}
@Override
protected Response<ChangeInfo> applyImpl(
BatchUpdate.Factory updateFactory, RevisionResource rsrc, RebaseInput input)
protected Response<ChangeInfo> applyImpl(RevisionResource rsrc, RebaseInput input)
throws UpdateException, RestApiException, IOException, PermissionBackendException {
// Not allowed to rebase if the current patch set is locked.
patchSetUtil.checkPatchSetNotLocked(rsrc.getNotes());

View File

@@ -24,7 +24,6 @@ import com.google.gerrit.server.edit.ChangeEditModifier;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.inject.Inject;
@@ -48,8 +47,7 @@ public class RebaseChangeEdit extends RetryingRestModifyView<ChangeResource, Inp
}
@Override
protected Response<Object> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input in)
protected Response<Object> applyImpl(ChangeResource rsrc, Input in)
throws AuthException, ResourceConflictException, IOException, PermissionBackendException {
Project.NameKey project = rsrc.getProject();
try (Repository repository = repositoryManager.openRepository(project)) {

View File

@@ -56,6 +56,7 @@ public class Restore extends RetryingRestModifyView<ChangeResource, RestoreInput
implements UiAction<ChangeResource> {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final BatchUpdate.Factory updateFactory;
private final RestoredSender.Factory restoredSenderFactory;
private final ChangeJson.Factory json;
private final ChangeMessagesUtil cmUtil;
@@ -65,6 +66,7 @@ public class Restore extends RetryingRestModifyView<ChangeResource, RestoreInput
@Inject
Restore(
BatchUpdate.Factory updateFactory,
RestoredSender.Factory restoredSenderFactory,
ChangeJson.Factory json,
ChangeMessagesUtil cmUtil,
@@ -73,6 +75,7 @@ public class Restore extends RetryingRestModifyView<ChangeResource, RestoreInput
ChangeRestored changeRestored,
ProjectCache projectCache) {
super(retryHelper);
this.updateFactory = updateFactory;
this.restoredSenderFactory = restoredSenderFactory;
this.json = json;
this.cmUtil = cmUtil;
@@ -82,8 +85,7 @@ public class Restore extends RetryingRestModifyView<ChangeResource, RestoreInput
}
@Override
protected Response<ChangeInfo> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, RestoreInput input)
protected Response<ChangeInfo> applyImpl(ChangeResource rsrc, RestoreInput input)
throws RestApiException, UpdateException, PermissionBackendException, IOException {
// Not allowed to restore if the current patch set is locked.
psUtil.checkPatchSetNotLocked(rsrc.getNotes());

View File

@@ -84,6 +84,7 @@ public class Revert extends RetryingRestModifyView<ChangeResource, RevertInput,
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final PermissionBackend permissionBackend;
private final BatchUpdate.Factory updateFactory;
private final GitRepositoryManager repoManager;
private final ChangeInserter.Factory changeInserterFactory;
private final ChangeMessagesUtil cmUtil;
@@ -101,6 +102,7 @@ public class Revert extends RetryingRestModifyView<ChangeResource, RevertInput,
@Inject
Revert(
PermissionBackend permissionBackend,
BatchUpdate.Factory updateFactory,
GitRepositoryManager repoManager,
ChangeInserter.Factory changeInserterFactory,
ChangeMessagesUtil cmUtil,
@@ -117,6 +119,7 @@ public class Revert extends RetryingRestModifyView<ChangeResource, RevertInput,
CommitUtil commitUtil) {
super(retryHelper);
this.permissionBackend = permissionBackend;
this.updateFactory = updateFactory;
this.repoManager = repoManager;
this.changeInserterFactory = changeInserterFactory;
this.cmUtil = cmUtil;
@@ -133,8 +136,7 @@ public class Revert extends RetryingRestModifyView<ChangeResource, RevertInput,
}
@Override
public Response<ChangeInfo> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, RevertInput input)
public Response<ChangeInfo> applyImpl(ChangeResource rsrc, RevertInput input)
throws IOException, RestApiException, UpdateException, NoSuchChangeException,
PermissionBackendException, NoSuchProjectException, ConfigInvalidException {
Change change = rsrc.getChange();

View File

@@ -36,7 +36,6 @@ import com.google.gerrit.server.project.ContributorAgreementsChecker;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.inject.Inject;
@@ -85,8 +84,7 @@ public class RevertSubmission
}
@Override
public Response<RevertSubmissionInfo> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource changeResource, RevertInput input)
public Response<RevertSubmissionInfo> applyImpl(ChangeResource changeResource, RevertInput input)
throws Exception {
if (!changeResource.getChange().isMerged()) {

View File

@@ -41,17 +41,21 @@ import com.google.inject.Singleton;
@Singleton
public class SetReadyForReview extends RetryingRestModifyView<ChangeResource, Input, String>
implements UiAction<ChangeResource> {
private final BatchUpdate.Factory updateFactory;
private final WorkInProgressOp.Factory opFactory;
@Inject
SetReadyForReview(RetryHelper retryHelper, WorkInProgressOp.Factory opFactory) {
SetReadyForReview(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
WorkInProgressOp.Factory opFactory) {
super(retryHelper);
this.updateFactory = updateFactory;
this.opFactory = opFactory;
}
@Override
protected Response<String> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
protected Response<String> applyImpl(ChangeResource rsrc, Input input)
throws RestApiException, UpdateException, PermissionBackendException {
rsrc.permissions().check(ChangePermission.TOGGLE_WORK_IN_PROGRESS_STATE);

View File

@@ -41,17 +41,21 @@ import com.google.inject.Singleton;
@Singleton
public class SetWorkInProgress extends RetryingRestModifyView<ChangeResource, Input, String>
implements UiAction<ChangeResource> {
private final BatchUpdate.Factory updateFactory;
private final WorkInProgressOp.Factory opFactory;
@Inject
SetWorkInProgress(WorkInProgressOp.Factory opFactory, RetryHelper retryHelper) {
SetWorkInProgress(
RetryHelper retryHelper,
BatchUpdate.Factory updateFactory,
WorkInProgressOp.Factory opFactory) {
super(retryHelper);
this.updateFactory = updateFactory;
this.opFactory = opFactory;
}
@Override
protected Response<String> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
protected Response<String> applyImpl(ChangeResource rsrc, Input input)
throws RestApiException, UpdateException, PermissionBackendException {
rsrc.permissions().check(ChangePermission.TOGGLE_WORK_IN_PROGRESS_STATE);

View File

@@ -23,7 +23,6 @@ import com.google.gerrit.server.git.BanCommitResult;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectResource;
import com.google.gerrit.server.restapi.project.BanCommit.BanResultInfo;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
@@ -46,8 +45,7 @@ public class BanCommit
}
@Override
protected Response<BanResultInfo> applyImpl(
BatchUpdate.Factory updateFactory, ProjectResource rsrc, BanCommitInput input)
protected Response<BanResultInfo> applyImpl(ProjectResource rsrc, BanCommitInput input)
throws RestApiException, UpdateException, IOException, PermissionBackendException {
BanResultInfo r = new BanResultInfo();
if (input != null && input.commits != null && !input.commits.isEmpty()) {

View File

@@ -75,7 +75,8 @@ public class RetryHelper {
CHANGE_UPDATE,
GROUP_UPDATE,
INDEX_QUERY,
PLUGIN_UPDATE
PLUGIN_UPDATE,
REST_REQUEST,
}
/**

View File

@@ -19,6 +19,8 @@ import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.git.LockFailureException;
import com.google.gerrit.server.update.RetryHelper.ActionType;
import java.util.concurrent.atomic.AtomicReference;
public abstract class RetryingRestModifyView<R extends RestResource, I, O>
@@ -40,7 +42,16 @@ public abstract class RetryingRestModifyView<R extends RestResource, I, O>
.onAutoTrace(traceId::set)
.build();
return retryHelper
.execute((updateFactory) -> applyImpl(updateFactory, resource, input), retryOptions)
.execute(
ActionType.REST_REQUEST,
() -> applyImpl(resource, input),
retryOptions,
t -> {
if (t instanceof UpdateException) {
t = t.getCause();
}
return t instanceof LockFailureException;
})
.traceId(traceId.get());
} catch (Exception e) {
Throwables.throwIfInstanceOf(e, RestApiException.class);
@@ -48,6 +59,5 @@ public abstract class RetryingRestModifyView<R extends RestResource, I, O>
}
}
protected abstract Response<O> applyImpl(BatchUpdate.Factory updateFactory, R resource, I input)
throws Exception;
protected abstract Response<O> applyImpl(R resource, I input) throws Exception;
}

View File

@@ -445,7 +445,7 @@ public class CommentsIT extends AbstractDaemonTest {
ChangeResource changeRsrc =
changes.get().parse(TopLevelResource.INSTANCE, IdString.fromDecoded(changeId));
RevisionResource revRsrc = revisions.parse(changeRsrc, IdString.fromDecoded(revId));
postReview.get().apply(batchUpdateFactory, revRsrc, input, timestamp);
postReview.get().apply(revRsrc, input, timestamp);
Map<String, List<CommentInfo>> result = getPublishedComments(changeId, revId);
assertThat(result).isNotEmpty();
CommentInfo actual = Iterables.getOnlyElement(result.get(comment.path));